Web安全之深度学习实战(txt+pdf+epub+mobi电子书下载)


发布时间:2020-06-01 12:01:01

点击下载

作者:刘焱

出版社:机械工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Web安全之深度学习实战

Web安全之深度学习实战试读:

前言

网络安全一直和AI相伴相生,从网络安全诞生的那一天起,人们就一直试图使用自动化的方式去解决安全问题。网络安全专家一直试图把自己对网络威胁的理解转换成机器可以理解的方式,比如黑白名单、正则表达式,然后利用机器强大的计算能力,夜以继日地从流量、日志、文件中寻找似曾相识的各类威胁。似乎这一切就是那么天经地义并无懈可击。但事情似乎又没有那么简单,机器其实并没有完全学到人的经验,网络安全专家一眼就可以识破的变形,对于机器却难以理解;更可怕的是,恶意程序数量呈指数级增长,各类新型攻击方式层出不穷,0day的出现早已超过一线明星出现在新闻头条的频率,依靠极其有限的网络专家总结的经验和几个安全厂商所谓的样本交换,已经难以应付现在的网络安全威胁。如果安全专家一眼就可以识破的威胁,机器也能够自动化发现甚至做出相应的响应,这已经是很大的进步;如果让机器可以像阿尔法狗理解围棋一样理解网络威胁,那将是巨大进步。事情又回到最初的那个问题,如何能让机器可以真正学会识别安全威胁?机器学习可能是一个不错的答案。

本书面向信息安全从业人员、大专院校计算机相关专业学生以及信息安全爱好者、机器学习爱好者,对于想了解人工智能的CTO、运维总监、架构师同样也是一本不错的科普书籍。如果读者看完本书,在工作学习中遇到问题时可以想起一到两种算法,那么我觉得就达到效果了;如果读者读完本书,可以像使用printf一样使用SVM、朴素贝叶斯等算法,那么这本书就相当成功了。

我写本书的初衷是帮助信息安全从业者了解机器学习,可以动手使用简单的机器学习算法解决实际问题。在写作中尽量避免生硬的说教,能用文字描述的尽量不用冷冰冰的公式,能用图和代码说明的尽量不用多余的文字。正如霍金所言“多写1个公式,少一半读者”,希望反之亦然。

机器学习应用于安全领域遇到的最大问题就是缺乏大量的黑样本,即所谓的攻击样本,尤其相对于大量的正常业务访问,攻击行为尤其是成功的攻击行为是非常少的,这就给机器学习带来了很大挑战。本书很少对不同算法进行横向比较,也是因为在不同场景下不同算法的确表现差别很大,很难说深度学习就一定比朴素贝叶斯好,也很难说支持向量机就比不过卷积神经网络,拿某个具体场景进行横评意义不大,毕竟选择算法不像购买SUV,可以拿几十个参数评头论足,最后还是需要大家结合实际问题去选择。

本书的第1章主要介绍了如何打造自己的深度学习工具箱,介绍了本书使用的TensorFlow、TFLearn等深度学习库的安装以及使用方法。第2章和第3章介绍了卷积神经网络和循环神经网络这两大深度学习算法的基础知识。第4章介绍在生产环境搭建机器学习平台需要使用的开源组件,包括Logstash、Kafka、Storm、Spark等,并且介绍了GPU和TPU的基础知识。第5章到第15章,介绍了11个使用机器学习技术解决实际安全问题的案例,包括验证码识别、垃圾邮件识别、负面评论识别、骚扰短信识别、Linux后门检测、用户行为分析与恶意行为检测、WebShell检测、智能扫描器、DGA域名检测、恶意程序分类识别、反信用卡欺诈,每个案例都使用互联网公开的数据集并配有基于Python的代码,代码和数据集可以在本书配套的GitHub下载。

本书是我所著机器学习三部曲的第二部,第一部主要以机器学习常见算法为主线,利用生活中的例子和具体安全场景来介绍机器学习常见算法,是机器学习入门书籍,便于读者可以快速上手。全部代码都能在普通PC上运行。本书将重点介绍深度学习,并以具体的11个案例介绍机器学习的应用,定位是面向具有一定机器学习基础或者致力于使用机器学习解决工作中问题的读者,本书将重点放在问题的解决而不是算法的介绍。由于深度学习通常计算量已经超过了PC的能力,部分代码需要在服务器甚至GPU上运行,不过这不影响大家的阅读与学习。第三部将重点介绍强化学习和对抗网络,并利用若干虚构安全产品或者项目来介绍如何让机器真正具备阿尔法狗级别的智能。遗憾的是,深度学习的优势发挥需要大量精准标注的训练样本,但是由于各种各样的原因,我只能在书中使用互联网上已经公开的数据集,这些数据量级往往很难发挥深度学习的优势,对于真正想在生产环境中验证想法的读者需要搜集更多样本。致谢

这里我要感谢我的家人对我的支持,本来工作就很忙,没有太多时间处理家务,写书更是花费了我大量的休息时间,我的妻子无条件承担起了全部家务,尤其是照料孩子等繁杂事务。我很感谢我的女儿,写书这段时间几乎没有时间陪她玩,她很懂事地自己玩,我想用这本书作为她的生日礼物送给她。我还要感谢吴怡编辑对我的支持和鼓励,让我可以坚持把这本书写完。最后还要感谢各位业内好友尤其是我boss对我的支持,排名不分先后:马杰@百度安全、冯景辉@百度安全、Tony@京东安全、程岩@京东安全、简单@京东安全、林晓东@百度基础架构、黄颖@百度IT、李振宇@百度AI、Lenx@百度安全、黄正@百度安全、郝轶@百度云、云鹏@百度无人车、阿文@丁牛、赵林林@微步在线、张宇平@数盟、谢忱@Freebuf、李新@Freebuf、李琦@清华、徐恪@清华、王宇@蚂蚁金服、王珉然@蚂蚁金服、王龙@蚂蚁金服、周涛@启明星辰、姚志武@借贷宝、刘静@安天、刘袁君@医渡云、廖威@易宝支付、尹毅@sobug、宋文宽@联想、团长@宜人贷、齐鲁@搜狐安全、吴圣@58安全、康宇@新浪安全、幻泉@i春秋、雅驰@i春秋、王庆双@i春秋、张亚同@i春秋、王禾@微软、李臻@paloalto、西瓜@四叶草、郑伟@四叶草、朱利军@四叶草、土夫子@XSRC、英雄马@乐视云、sbilly@360、侯曼@360、高磊@滴滴、高磊@爱加密、高渐离@华为、刘洪善@华为云、宋柏林@一亩田、张昊@一亩田、张开@安恒、李硕@智联、阿杜@优信拍、李斌@房多多、李程@搜狗、姚聪@face+、李鸣雷@金山云、吴鲁加@小密圈,最后我还要感谢我的亲密战友陈燕、康亮亮、蔡奇、哲超、新宇、子奇、月升、王磊、碳基体、刘璇、钱华钩、刘超、王胄、吴梅、冯侦探、冯永校。

我平时在Freebuf专栏以及i春秋分享企业安全建设以及人工智能相关经验与最新话题,同时也运营我的微信公众号“兜哥带你学安全”、知识星球(原名小密圈)“Web安全之机器学习”,欢迎大家关注并在线交流。之前没有使用过知识星球的读者可以在各类应用市场上搜索。

本书使用的代码和数据均在GitHub上发布,地址为:https://github.com/duoergun0729/2book,代码层面任何疑问可以在GitHub上直接反馈。第1章打造深度学习工具箱

在本系列图书的第一本《Web安全之机器学习入门》中,我们以常见安全问题为背景介绍了常见的机器学习算法,主要以KNN、SVM、朴素贝叶斯等浅层学习算法为主。以Scikit-Learn为代表的机器学习开发库帮助我们可以很便捷地在单机环境下验证我们的想法。近几年深度学习发展迅速,以TensorFlow为代表的一批优秀的深度学习开发库大大降低了大家学习使用深度学习技术的门槛。作为本书的第1章,本章将帮助大家打造自己的深度学习工具箱,并结合实际例子介绍TensorFlow、TFLearn、PaddlePaddle以及Karas的使用方法。

本章代码请参考本书配套GitHub中的tools.py。1.1 TensorFlow

TensorFlow是谷歌的第二代人工智能学习系统,其名称来源于本身的运行原理。Tensor意味着N维数组,Flow意味着基于数据流图的计算,TensorFlow为Tensor从流图的一端流动到另一端计算过程。所以也可以把TensorFlow当做将复杂的数据结构传输至人工智能神经网中进行分析和处理的系统。

TensorFlow可用于语音识别或图像识别等多项机器深度学习领域,是对2011年开发的深度学习基础架构DistBelief进行了各方面的改进,它可在小到一部智能手机、大到数千台数据中心服务器的各种设备上运行。1.1.1 安装[1]

TensorFlow支持非常丰富的安装方式。

1.Ubuntu/Linux。# 仅使用CPU的版本 $ pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.5.0-cp27-none-linux_x86_64.whl # 开启 GPU 支持的版本 (安装该版本的前提是已经安装了 CUDA sdk) $ pip install https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.5.0-cp27-none-linux_x86_64.whl

2.Mac OS X。

在Mac OS X系统上,我们推荐先安装homebrew,然后执行brew install python,以便能够使用homebrew中的Python安装TensorFlow:# 当前版本只支持 CPU $ pip install https://storage.googleapis.com/tensorflow/mac/tensorflow-0.5.0-py2-none-any.whl

3.基于Docker的安装。$ docker run -it b.gcr.io/tensorflow/tensorflow

该命令将启动一个已经安装好TensorFlow及相关依赖的容器:

4.基于VirtualEnv的安装。

官方文档推荐使用VirtualEnv创建一个隔离的容器来安装TensorFlow,这是可选的,但是这样做能使排查安装问题变得更容易。VirtualEnv通过创建独立Python开发环境的工具,来解决依赖、版本以及间接权限问题。比如,一个项目依赖Django1.3,而当前全局开发环境为Django1.7,版本跨度过大,导致的不兼容使项目无法正常[2]运行,使用VirtualEnv可以解决这些问题。

首先,安装所有必备工具:# 在Linux上: $ sudo apt-get install python-pip python-dev python-virtualenv # 在 Mac 上: # 如果还没有安装 pip $ sudo easy_install pip $ sudo pip install --upgrade virtualenv

接下来,建立一个全新的VirtualEnv环境。为了将环境建在~/tensorflow目录下,执行如下代码:$ virtualenv --system-site-packages ~/tensorflow $ cd ~/tensorflow

然后,激活VirtualEnv:$ source bin/activate # 如果使用 bash $ source bin/activate.csh # 如果使用 csh (tensorflow)$ # 终端提示符应该发生变化

在VirtualEnv内,安装TensorFlow:(tensorflow)$ pip install --upgrade <$url_to_binary.whl>

接下来,使用类似命令运行TensorFlow程序:(tensorflow)$ cd tensorflow/models/image/mnist (tensorflow)$ python convolutional.py # 当使用完 TensorFlow (tensorflow)$ deactivate

[1] http://www.tensorfly.cn/tfdoc/get_started/os_setup.html

[2] http://www.jianshu.com/p/08c657bd34f11.1.2 使用举例

TensorFlow的API使用起来比较繁琐,通常直接使用针对其API的高层封装TFLearn即可,具体实现请参考下节TFLearn的使用举例。1.2 TFLearn

TFLearn是一个模块化和透明的深度学习库,构建在TensorFlow之上,它为TensorFlow提供高层次API,目的是快速搭建试验环境,同时保持对TensorFlow的完全透明和兼容性。[1]

TFLearn具有以下特点:

·容易使用和易于理解的高层次API用于实现深度神经网络,附带教程和例子。

·通过高度模块化的内置神经网络层、正则化器、优化器等进行快速原型设计。

·强大的辅助函数,训练任意TensorFlow图,支持多输入、多输出和优化器。

·简单而美观的图可视化,具有关于权值、梯度、特征图等细节。

·无需人工干预,可使用多CPU、多GPU。

本书的主要代码都是基于TFLearn开发的。

1.安装。

TFLearn的安装推荐使用使用pip工具:pip install tflearn

如果需要使用源码安装,可以直接从GitHub上下载对应源码:https://github.com/tflearn

然后进入TFLearn目录安装即可:python setup.py install

2.使用举例。

TFLearn自带MNIST数据,使用函数mnist.load_data接口,并且可以通过指定one_hot=True直接获取使用独热编码的标签:X, Y, testX, testY = mnist.load_data(one_hot=True)

构造一个隐藏层为2层,每层核数分别为64、64,输出层核数为10的多层感知机,使用fully_connected函数即可完成构造全连接网络的工作,使用tflearn.input_data定义输入数据大小。为了避免过拟合,每层之间使用Dropout函数进行部分丢失处理:# Building deep neural networkinput_layer = tflearn.input_data(shape=[None, 784])dense1 = tflearn.fully_connected(input_layer, 64, activation='tanh', regularizer='L2', weight_decay=0.001)dropout1 = tflearn.dropout(dense1, 0.8)dense2 = tflearn.fully_connected(dropout1, 64, activation='tanh', regularizer='L2', weight_decay=0.001)dropout2 = tflearn.dropout(dense2, 0.8)softmax = tflearn.fully_connected(dropout2, 10, activation='softmax')

使用多层感知机进行训练,通过n_epoch设置训练的轮数:# Trainingmodel = tflearn.DNN(net, tensorboard_verbose=0)model.fit(X, Y, n_epoch=20, validation_set=(testX, testY), show_metric=True, run_id="dense_model")

经过20轮的训练后,准确率达到了99.54%:Training Step: 17200 | total loss: 0.43454 | time: 5.444s| SGD | epoch: 020 | loss: 0.43454 - top3: 0.9685 | val_loss: 0.10618 - val_acc: 0.9954 -- iter: 55000/55000

[1] https://zhuanlan.zhihu.com/p/253220661.3 PaddlePaddle

PaddlePaddle是百度开源的深度学习库,2016年9月27日,百度宣布其全新的深度学习开源平台PaddlePaddle在开源社区GitHub及百度大脑平台开放,供广大开发者下载使用。百度成为继Google、Facebook、IBM后另一个将人工智能技术开源的科技巨头,同时也是国内首个开源深度学习平台的科技公司。PaddlePaddle的前身是百度于2013年自主研发的深度学习平台Paddle(Parallel Distributed Deep Learning,并行分布式深度学习),且一直为百度内部工程师研发使用。全球各大科技巨头开源的深度学习平台都极具各自的技术特点。百度由于其自身在搜索、图像识别、语音语义识别理解、情感分析、机器翻译、用户画像推荐等多领域都有业务应用,PaddlePaddle则表现得更加全面,是一个相对全功能的深度学习框架。目前,PaddlePaddle已实现CPU/GPU单机和分布式模式,同时支持海量数据训练、数百台机器并行运算,以应对大规模的数据训练。此外,PaddlePaddle具备高质量GPU代码,提供了机器翻译、推荐、图像分类、情感分析等功能。

目前,PaddlePaddle已在百度30多项主要产品和服务之中发挥着作用,如外卖的预估出餐时间、预判网盘故障时间点、精准推荐用户所需信息、海量图像识别分类、字符识别、病毒和垃圾信息检测、机器翻译和自动驾驶等领域。以外卖行业为例,外卖员等待商家出餐的时间耗时严重,百度将不同时段商家的客流量、菜品的制作时间和订单量等数据交给了PaddlePaddle,经过对海量数据的深度学习处理,如今,百度外卖的内部系统可以预估每个商家菜品出餐时间,及时告知外卖员,提高了送餐效率,系统也可以更加合理地规划取餐和送餐[1]的路线。

[1] http://tech.sina.com.cn/i/2016-09-27/doc-ifxwevmc5593979.shtml1.3.1 安装

PaddlePaddle提供数个预编译的二进制文件来进行安装,包括Docker镜像和Ubuntu的deb安装包等。

1.基于Docker容器使用方式

PaddlePaddle的编译环境打包成了一个镜像,称为开发镜像,里面涵盖了PaddlePaddle需要的所有编译工具。编译出来的PaddlePaddle也打包成一个镜像,称为生产镜像,里面涵盖了运行所需的所有环境。每次发布新版本的时候都会发布对应版本的生产镜像以及开发镜像。运行镜像包括纯CPU版本和GPU版本及其对应的非[1]AVX版本。

交互方式运行开发镜像:docker run -it --rm paddlepaddle/paddle:-dev /bin/bash

后台进程方式运行容器:docker run -d -p 2202:22 -p 8888:8888 paddledev/paddle:-dev

然后用密码root SSH进入容器:ssh -p 2202 root@localhost

2.Ubuntu部署PaddlePaddle

安装包的下载地址是:https://github.com/PaddlePaddle/Paddle/releases

它包含4个版本:

·CPU版本:支持主流X86处理器平台,使用了AVX指令集。

·CPU-NOAVX版本:支持主流X86处理器平台,没有使用AVX指令集。

·GPU版本:支持主流X86处理器平台,支持NVIDIA CUDA平台,使用了AVX指令集。

·GPU-NOAVX版本:支持主流X86处理器平台,支持NVIDIA CUDA平台,没有使用AVX指令集。

下载完相关安装包后,执行如下命令:sudo apt-get install gdebi gdebi paddle-*-cpu.deb

或者如下命令:dpkg -i paddle-*-cpu.deb apt-get install -f

在用dpkg-i的时候如果报一些依赖未找到的错误是正常的,在apt-get install-f里会继续安装PaddlePaddle。

安装完成后,可以使用命令paddle version查看安装后的Paddle

[2]版本:PaddlePaddle 0.8.0b1, compiled withwith_avx: ONwith_gpu: OFFwith_double: OFFwith_python: ONwith_rdma: OFFwith_timer: OFFwith_predict_sdk:

[1] http://www.paddlepaddle.org/doc_cn/getstarted/build_and_install/docker_install_cn.html

[2] http://www.paddlepaddle.org/doc_cn/getstarted/build_and_install/ubuntu_install_cn.html1.3.2 使用举例

以识别MNIST数据集为例,关于MNIST数据集的详细介绍请参考本书第5章。

下面代码实现了一个含有两个隐藏层的多层感知器,其中两个隐藏层的激活函数均采用ReLU,输出层的激活函数用Softmax:def multilayer_perceptron(img): hidden1 = paddle.layer.fc(input=img, size=128, act=paddle.activation.Relu()) hidden2 = paddle.layer.fc(input=hidden1, size=64, act=paddle.activation.Relu()) predict = paddle.layer.fc(input=hidden2, size=10, act=paddle.activation.Softmax()) return predict

通过layer.data调用来获取数据,然后调用分类器得到分类结果。训练时,对该结果计算其损失函数,分类问题常常选择交叉熵损失函数:paddle.init(use_gpu=False, trainer_count=1) images = paddle.layer.data( name='pixel', type=paddle.data_type.dense_vector(784) ) label = paddle.layer.data( name='label', type=paddle.data_type.integer_value(10)) predict = multilayer_perceptron(images) #多层感知器 cost = paddle.layer.classification_cost(input=predict, label=label)

训练过程是完全自动的,event_handler里打印的日志如下所示,最后准确率为97.66%:# Pass 0, Batch 0, Cost 2.780790, {'classification_error_evaluator': 0.9453125} # Pass 0, Batch 100, Cost 0.635356, {'classification_error_evaluator': 0.2109375} # Pass 0, Batch 200, Cost 0.326094, {'classification_error_evaluator': 0.1328125} # Pass 0, Batch 300, Cost 0.361920, {'classification_error_evaluator': 0.1015625} # Pass 0, Batch 400, Cost 0.410101, {'classification_error_evaluator': 0.125} # Test with Pass 0, Cost 0.326659, {'classification_error_evaluator': 0.09470000118017197}1.4 Karas

Keras是一个高级别的Python神经网络框架,能在TensorFlow或者Theano上运行。Keras的作者、谷歌AI研究员Francois Chollet宣布了一条激动人心的消息,Keras将会成为第一个被添加到TensorFlow核心中的高级别框架,这将会使Keras变成Tensorflow的默认API。

Keras的特点是:

·可以快速简单地设计出原型。

·同时支持卷积网络和循环网络,以及两者的组合。

·支持任意的连接方案(包括多输入和多输出)。

Keras的在线文档内容非常丰富,地址为:https://keras.io/

1.安装

Keras的安装非常简便,使用pip工具即可:pip install keras

如果需要使用源码安装,可以直接从GitHub上下载对应源码:https://github.com/fchollet/keras

然后进入Keras目录安装即可:python setup.py install

2.使用举例

以识别MNIST数据集为例,关于MNIST数据集的详细介绍请参考本书第5章。本章主要是给大家概要介绍如何使用Keras。

Keras自带了MNIST数据集,使用mnist.load_data()加载即可:# the data, shuffled and split between train and test sets(x_train, y_train), (x_test, y_test) = mnist.load_data()

MNIST中的图片大小为28×28的矩阵,为了处理方便,把28×28的矩阵转换成长度为784的向量:x_train = x_train.reshape(60000, 784)x_test = x_test.reshape(10000, 784)x_train = x_train.astype('float32')x_test = x_test.astype('float32')x_train /= 255x_test /= 255

图片识别的结果是0~9这10个数字。通常神经网络算法在处理时,习惯将输出以独热编码的形式展现,即所谓One-Hot编码,又称“一位有效编码”。其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都有它独立的寄存器位,并且在任意时候,其中只有一位有效。比如以二分类问题为例,结果为真表示为1,反之为0;使用独热编码,结果为真表示为10,反之为01。在Karas中可以使用keras.utils.to_categorical很方便地进行转换:# convert class vectors to binary class matricesy_train = keras.utils.to_categorical(y_train, num_classes)y_test = keras.utils.to_categorical(y_test, num_classes)

下面是整个环节的重点,构造一个隐藏层为2层,每层节点数分别为512、512,输出层节点数为10的多层感知机,使用Dense函数即可完成构造全连接网络的工作,其中第一层需要定义输入数据的形状,具体定义方式在input_shape属性指定。为了避免过拟合,每层之间使用Dropout函数进行部分丢失处理,适度的丢失数据不会影响分类识别效果,就好比识别一张照片时适度遮住一部分,不会影响分类识别结果:model = Sequential()model.add(Dense(512, activation='relu', input_shape=(784,)))model.add(Dropout(0.2))model.add(Dense(512, activation='relu'))model.add(Dropout(0.2))model.add(Dense(10, activation='softmax'))

完成多层感知机的结构定义后,就可以使用compile函数“编译”整个网络,让其工作:model.summary()model.compile(loss='categorical_crossentropy', optimizer=RMSprop(), metrics=['accuracy'])

整个训练过程需要定义训练数据集和测试数据集,同时定义训练的轮数,通常认为训练轮数为5~20比较合适,轮数太少训练不充分,轮数太多则训练时间过长:history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test, y_test))

最后评估整个训练的效果,经过20轮训练,准确率为98.12%:score = model.evaluate(x_test, y_test, verbose=0)print('Test loss:', score[0])print('Test accuracy:', score[1])

输出结果为:Epoch 20/2060000/60000 [==============================] - 11s - loss: 0.0201 - acc: 0.9950 - val_loss: 0.1224 - val_acc: 0.9812('Test loss:', 0.12236141463853964)('Test accuracy:', 0.98119999999999996)1.5 本章小结

本章介绍了如何打造自己的深度学习工具箱,介绍了TensorFlow、TFLearn、Paddle-Paddle以及Karas的安装方法,并结合常见的MNIST数据集介绍了以上工具箱的使用方式,各种工具箱识别准确率不同,这不代表工具本身的优劣。这里只是给大家一个基本的演示,初次接触这些代码可能会非常茫然,相信通过后面章节的介绍,大家最后会熟练掌握这些代码。第2章卷积神经网络

深度学习模型中的卷积神经网络(Convolution Neural Network,CNN)近年来在图像领域取得了惊人的成绩,CNN直接利用图像像素信息作为输入,最大程度保留了输入图像的所有信息,通过卷积操作进行特征的提取和高层抽象,模型输出直接是图像识别的结果。这种基于“输入-输出”直接端到端的学习方法取得了非常好的效果,得到了广泛的应用。本章重点介绍CNN的基本原理、常见的CNN结构以及代码实现,还介绍了基于CNN的文本分类处理。

本章涉及的代码请参考本书GitHub的cnn.py文件。2.1 传统的图像分类算法

图像分类是根据图像的原始信息将不同类别图像区分开来,是计算机视觉中重要的基本问题,也是图像检测、图像分割、物体跟踪、行为分析等其他高层视觉任务的基础。图像分类在很多领域有广泛应用,包括安防领域的人脸识别和智能视频分析,交通领域的交通场景识别,互联网领域基于内容的图像检索和相册自动归类,医学领域的[1]图像识别等,如图2-1所示。

在CNN出现之前,图像分类算法依赖于复杂的特征工程。常用的特征提取方法包括SIFT(Scale-Invariant Feature Transform,尺度不变特征转换)、HOG(Histogram of Oriented Gradient,方向梯度直方图)、LBP(Local Bianray Pattern,局部二值模式)等,常用的分类算法为SVM。图2-1 图像分类识别花的不同品种

[1] http://book.paddlepaddle.org/index.cn.html2.2 基于CNN的图像分类算法

人们尝试直接把原始图像作为输入,通过深度学习算法直接进行图像分类,从而绕过复杂的特征工程。下面介绍几个重要技术点。2.2.1 局部连接

常见的深度学习算法都是全连接形式,所谓全连接,就是第n-1层的任意一个节点,都和第n层所有节点有连接,如图2-2所示。图2-2 隐藏层内部全连接形式

同时,临近输入层的隐藏层的任意节点与输入层的全部节点都有连接,如图2-3所示。图2-3 输入层与隐藏层全连接形式

以一个大小为1000×1000的灰度图像为例,输入层节点数量为1000×1000=1000000,隐藏层节点数量也为1000×1000=1000000,12仅输入层与隐藏层的连接就需要1000000×1000000=10,几乎是个天文数字,如此巨大的计算量阻碍了深度学习在图像分类方向的应用。

事情的转机来自于生物学的一个发现。人们在研究猫的视觉神经细胞时发现,一个视觉神经元只负责处理视觉图像的一小块,这一小块称为感受野(Receptive Field),类比在图像分类领域,识别一个图像是何种物体时,一个点与距离近的点之间的关联非常紧密,但是和距离远的点之间关系就不大了,甚至足够远的时候就可以忽略不计[1],如图2-4所示。图2-4 全连接与局部连接

具体到深度学习算法上,隐藏层与输入层之间,隐藏层的一个节点只处理一部分输入层结点的数据,形成局部连接。还是接上面的例子,假设每个隐藏层的节点只处理10×10大小的数据,也就是说每个隐藏层的节点只与输入层的100个节点连接,这样在隐藏层节点数量和输入层节点数量不变的情况下,输入层与隐藏层的连接需要81000000×100=10,是全连接的万分之一。虽然计算量下降不少,但是依然十分巨大。局部连接不会减少隐藏层的节点数量,减少的是隐藏层和输入层之间的连接数。

[1] http://blog.csdn.net/stdcoutzyx/article/details/415966632.2.2 参数共享

本质上隐藏层的一个节点与输入层一个节点的连接,对应的就是一个连接参数,大量的连接也就意味着大量的参数需要计算,仅依靠局部连接技术是无法进一步减少计算量的,于是人们又提出了参数共享方法。所谓的参数共享是基于这样一个假设:一部分图像的统计特性与完整图像的特性相同。回到上面的例子,每个隐藏层的节点只与输入层的100个节点连接,这样每个隐藏层节点就具有100个参数,8全部隐藏层就具有1000000×100=10个参数,使用参数共享后,每个隐藏层的节点都具有完全相同的参数,全部隐藏层就只有100个参数需要计算了,这大大减少了计算量,而且即使处理更大的图像,只要单一隐藏层节点与输入层连接的个数不变,全部隐藏层的参数个数也不变。这种共享参数的机制,可以理解为针对图像的卷积操作。假设如图2-5所示,具有一个4×4大小的图像和一个2×2大小的卷积核。图2-5 原始图像与卷积核

大小为2×2的卷积核对原始图像第1个2×2的图像块进行卷积操作,得到卷积结果为2,如图2-6所示。图2-6 卷积核对原始图像第1个2×2的块进行处理

大小为2×2的卷积核对原始图像第2个2×2的图像块进行卷积操作,得到卷积结果为1,如图2-7所示。图2-7 卷积核对原始图像第2个2×2的块进行处理

如果大小为2×2的卷积核依次对原始图像进行卷积操作,移动的步长为2,最终获得一个2×2的新图像,如图2-8所示。图2-8 卷积核对原始图像处理后的结果

可见卷积处理后图像的大小与卷积核的大小无关,仅与步长有关,对应的隐藏层的节点个数也仅与步长有关。另外需要说明的是,卷积核处理图像边际时会出现数据缺失,这时候需要将图像补全,常见的补全方式有两种,same模式和valid模式,same模式会使用0数据补全,而且保持生成图像与原始图像大小一致。

如果使用same模式,大小为2×2的卷积核依次对原始图像进行卷积操作,移动的步长为1,最终获得一个4×4的新图像,如图2-9所示。这里需要再次强调,当步长为1时,无论卷积核大小如何,处理前后图像大小不变;只有当步长大于1时,处理后的图像才会变小。图2-9 卷积核使用same模式对原始图像处理后的结果2.2.3 池化

通过局部连接和参数共享后,我们针对1000×1000的图像,使用卷积核大小为10×10,卷积步长为1,处理后得到的隐藏层节点个数6为1000×1000=10,计算量还是太大。为了解决这个问题,首先回忆一下,我们之所以决定使用卷积后的特征是因为图像具有一种“静态性”的属性,这也就意味着在一个图像区域有用的特征极有可能在另一个区域同样适用。因此,为了描述大的图像,一个很自然的想法就是对不同位置的特征进行聚合统计,例如,人们可以计算图像一个区域上的某个特定特征的平均值(或最大值)。这种聚合的操作就叫做池化。常见的池化大小为2×2、3×3等,假设隐藏层节点个数为4×4,使用2×2大小池化,取最大值,过程如图2-10所示。图2-10 池化处理

隐藏层节点个数为1000×1000的神经网络,经过2×2池化后,得4到的隐藏层节点个数为500×500=25×10。2.2.4 典型的CNN结构及实现

典型的CNN包含卷积层、全连接层等组件,并采用softmax多类别分类器和多类交叉熵损失函数,一个典型的卷积神经网络如图2-11所示。我们先介绍用来构造CNN的常见组件。图2-11 典型的CNN结构

·卷积层,执行卷积操作提取底层到高层的特征,发掘图片局部关联性质和空间不变性质。

·池化层,通过抽取卷积输出特征图中局部区块的最大值或者均值,执行降采样操作。降采样也是图像处理中常见的一种操作,可以过滤掉一些不重要的高频信息。

·全连接层,输入层到隐藏层的神经元是全部连接的。

·非线性变化,卷积层、全连接层后面一般都会接非线性变化层,例如Sigmoid、Tanh、ReLu等来增强网络的表达能力,在CNN里最常使用的是ReLu激活函数。

·Dropout,在模型训练阶段随机让一些隐层节点不工作,提高神经网络的泛化能力,一定程度上可防止过拟合。

这一点就好比人眼在识别图的时候,适当遮住一部分图像并不会影响识别结果一样。相对于浅层学习的SVM、KNN和朴素贝叶斯等,深度学习由于参数众多,更容易出现过拟合的现象,所以一般都需要使用Dropout的机制。

以处理经典的MNIST数据集为例,MNIST数据集作为一个简单的计算机视觉数据集,包含一系列如图2-12所示的手写数字图片和对应的标签。图片是28×28的像素矩阵,标签则对应着0~9的10个数字。每张图片都经过了大小归一化和居中处理。图2-12 MNIST图片示例

处理MNIST的CNN结构如图2-13所示,这是一个TensorFlow的结构输出图。图2-13 典型的CNN结构(TensorFlow)

简化表示的结构图如图2-14所示,TensorFlow中将处理的数据统一抽象为张量,即所谓的Tensor,原始大小为28×28的图像可以抽象成大小为28×28张量,张量依次经过:

1)卷积核大小为3×3数量为32的卷积处理。

2)池化大小为2×2的池化处理。

3)卷积核大小为3×3数量为64的卷积处理。

4)池化大小为2×2的池化处理以及最后的全连接处理。

5)最后得到长度为10的一维张量,对应正好是图像识别后的结果,即数字0~9。图2-14 简化的典型CNN结构

完整的处理流程如图2-15所示,其中Dropout合并到全连接处理中没有画出来。图2-15 典型的CNN结构完整处理流程

下面我们基于TensorFlow一步一步使用代码实现上述过程。

每张图片大小为28×28,可以当做一个28×28的矩阵,CNN输入层的大小为28×28,由于图像是灰度图像,每个像素取值为0或者1,定义输入为[None,28,28,1],这样就获得了大小为28×28的张量:network = input_data(shape=[None, 28, 28, 1], name='input')

使用卷积处理,卷积核大小为3×3,卷积核数量为32,可以理解为通过3×3大小的卷积操作,提取32种特征,处理后的张量大小为28×28×32,激活函数使用relu:network = conv_2d(network, 32, 3, activation='relu', regularizer="L2")

使用池化处理,池化大小为2×2,处理后的张量大小为14×14×32:network = max_pool_2d(network, 2)

使用卷积处理,卷积核大小为3×3,卷积核数量为64,可以理解为通过3×3大小的卷积操作,提取64种特征,处理后的张量大小为14×14×64:network = conv_2d(network, 64, 3, activation='relu', regularizer="L2")

使用池化处理,池化大小为2×2,处理后的张量大小为7×7×64:network = max_pool_2d(network, 2)

标准化处理张量,将大小为7×7×64的张量转化为长度为3136的一维张量,并与节点数为128的隐藏层进行全连接,为了避免过拟合,使用Dropout让部分节点临时失效。其中函数local_response_normalization即local response normalization最早是由Krizhevsky和Hinton在关于ImageNet的论文里面使用的一种数据标准化方法:network = local_response_normalization(network)network = fully_connected(network, 128, activation='tanh')network = dropout(network, 0.8)

再与节点数为256的隐藏层进行全连接,为了避免过拟合,继续使用Dropout让部分节点临时失效:network = fully_connected(network, 256, activation='tanh')network = dropout(network, 0.8)

最后再与节点数为10的输出层进行全连接,获得长度为10的一维张量,至此我们使用CNN,完成了大小为28×28的张量到大小为1×10的张量的训练转化:network = fully_connected(network, 10, activation='softmax')network = regression(network, optimizer='adam', learning_rate=0.01, loss='categorical_crossentropy', name='target')

值得一提的是,这里使用了多种激活函数,常见的激活函数有:sigmoid函数、tanh函数、ReLU函数,如图2-16~图2-18所示。图2-16 sigmoid函数图2-17 tanh函数图2-18 ReLU函数2.2.5 AlexNet的结构及实现

AlexNet是在2012年发表的一个经典之作,并在当年取得了ImageNet最好成绩,其官方提供的数据模型,准确率达到57.1%,top1~5达到80.2%。与传统的机器学习分类算法相比,这个结果已经相当出色。

AlexNet一共有8层组成,其中3个卷积层5个全连接层,如图2-19所示。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载