Python人工智能 | 九.卷积神经网络CNN原理详解及TensorFlow编写CNN

也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大

少走了弯路,也就错过了风景,无论如何,感谢经历

更多关于Android安全的知识,可前往:

本篇文章转载自公众号[娜璋AI安全之家]

基础性文章,希望对您有所帮助,如果文章中存在错误或不足之处,还请海涵~作者作为人工智能的菜鸟,希望大家能与我在这一笔一划的博客中成长起来。写了这么多年博客,尝试第一个付费专栏,但更多博客尤其基础性文章,还是会继续免费分享,但该专栏也会用心撰写,望对得起读者,共勉!

文章目录:

一.卷积神经网络原理

1.什么是CNN

2.CNN原理

二.TensorFlow实现CNN

三.总结


AI-for-TensorFlow


AI-for-Keras


一.卷积神经网络原理

1.什么是CNN

神经网络是由很多神经层组成,每一层神经层中存在很多神经元,这些神经元是识别事物的关键,当输入是图片时,其实就是一堆数字。

首先,卷积是什么意思呢?卷积是指不在对每个像素做处理,而是对图片区域进行处理,这种做法加强了图片的连续性,看到的是一个图形而不是一个点,也加深了神经网络对图片的理解。

卷积神经网络批量过滤器,持续不断在图片上滚动搜集信息,每一次搜索都是一小块信息,整理这一小块信息之后得到边缘信息。比如第一次得出眼睛鼻子轮廓等,再经过一次过滤,将脸部信息总结出来,再将这些信息放到全神经网络中进行训练,反复扫描最终得出的分类结果。如下图所示,猫的一张照片需要转换为数学的形式,这里采用长宽高存储,其中黑白照片的高度为1,彩色照片的高度为3(RGB)。

过滤器搜集这些信息,将得到一个更小的图片,再经过压缩增高信息嵌入到普通神经层上,最终得到分类的结果,这个过程即是卷积。Convnets是一种在空间上共享参数的神经网络,如下图所示,它将一张RGB图片进行压缩增高,得到一个很长的结果。

2.CNN原理

假设你有一张小猫咪的照片,如下图所示,它可以被表示为一个博饼,它有宽度(width)和高度(height),并且由于天然存在红绿蓝三色,它还拥有RGB厚度(depth),此时你的输入深度为3。

假设我们现在拿出图片的一小块,运行一个具有K个输出的小神经网络,像图中一样把输出表示为垂直的一小列。

在不改变权重的情况下,通过小神经网络滑动扫遍整个图片,就像我们拿着刷子刷墙一样水平垂直的滑动。

此时,输出端画出了另一幅图像,如下图中红色区域所示。它与之前的宽度和高度不同,更重要的是它跟之前的深度不同,而不是仅仅只有红绿蓝,现在你得到了K个颜色通道,这种操作称为——卷积。

如果你的块大小是整张图片,那它跟普通的神经网络层没有任何区别,正是由于我们使用了小块,我们有很多小块在空间中共享较少的权重。卷积不在对每个像素做处理,而是对图片区域进行处理,这种做法加强了图片的连续性,也加深了神经网络对图片的理解。

一个卷积网络是组成深度网络的基础,我们将使用数层卷积而不是数层的矩阵相乘。如下图所示,让它形成金字塔形状,金字塔底是一个非常大而浅的图片,仅包括红绿蓝,通过卷积操作逐渐挤压空间的维度,同时不断增加深度,使深度信息基本上可以表示出复杂的语义。同时,你可以在金字塔的顶端实现一个分类器,所有空间信息都被压缩成一个标识,只有把图片映射到不同类的信息保留,这就是CNN的总体思想。

上图的具体流程如下:

首先,这是有一张彩色图片,它包括RGB三原色分量,图像的长和宽为256*256,三个层面分别对应红(R)、绿(G)、蓝(B)三个图层,也可以看作像素点的厚度。

其次,CNN将图片的长度和宽度进行压缩,变成12812816的方块,压缩的方法是把图片的长度和宽度压小,从而增高厚度。

再次,继续压缩至646464,直至3232256,此时它变成了一个很厚的长条方块,我们这里称之为分类器Classifier。该分类器能够将我们的分类结果进行预测,MNIST手写体数据集预测结果是10个数字,比如[0,0,0,1,0,0,0,0,0,0]表示预测的结果是数字3,Classifier在这里就相当于这10个序列。

最后,CNN通过不断压缩图片的长度和宽度,增加厚度,最终会变成了一个很厚的分类器,从而进行分类预测。

如果你想实现它,必须还要正确实现很多细节。此时,你已经接触到了块和深度的概念,块(PATCH)有时也叫做核(KERNEL),如下图所示,你堆栈的每个薄饼都被叫做特征图(FeatureMap),这里把三个特性映射到K个特征图中,PATCH/KERNEL的功能是从图片中抽离一小部分进行分析,每次抽离的小部分都会变成一个长度、一个宽度、K个厚度的数列。

另一个你需要知道的概念是——步幅(STRIDE)。它是当你移动滤波器或抽离时平移的像素的数量,每一次跨多少步去抽离图片中的像素点。

如果步幅STRIDE等于1,表示每跨1个像素点抽离一次,得到的尺寸基本上和输入相同。

如果步幅STRIDE等于2,表示每次跨2个像素点抽离,意味着变为一半的尺寸。它收集到的信息就会被缩减,图片的长度和宽度被压缩了,压缩合并成更小的一块立方体。

压缩完之后再合并成一个立方体,它就是更小的一块立方体,包含了图片中的所有信息。

抽离图片信息的方式称为PADDING(填充),一般分为两种:

VALIDPADDING:抽出来这层比原先那层图片宽和长裁剪了一点,抽取的内容全部是图片内的。

SAMEPADDING:抽离出的那层与之前的图片一样的长和宽,抽取的内容部分再图片外,图片外的值用0来填充。

研究发现,卷积过程会丢失一些信息,比如现在想跨2步去抽离原始图片的重要信息,形成长宽更小的图片,该过程中可能会丢失重要的图片信息。为了解决这个问题,通过POOLING(持化)可以避免。其方法是:卷积时不再压缩长宽,尽量保证更多信息,压缩工作交给POOLING。经过图片到卷积,持化处理卷积信息,再卷积再持化,将结果传入两层全连接神经层,最终通过分类器识别猫或狗。

总结:整个CNN从下往上依次经历“图片-卷积-持化-卷积-持化-结果传入两层全连接神经层-分类器”的过程,最终实现一个CNN的分类处理。

IMAGE图片

CONVOLUTION图层

MAXPOOLING更好地保存原图片的信息

CONVOLUTION图层

MAXPOOLING更好地保存原图片的信息

FULLYCONNECTED神经网络隐藏层

FULLYCONNECTED神经网络隐藏层

CLASSIFIER分类器

写到这里,CNN的基本原理讲解完毕,希望大家对CNN有一个初步的理解。同时建议大家处理神经网络时,先用一般的神经网络去训练它,如果得到的结果非常好,就没必要去使用CNN,因为CNN结构比较复杂。

二.TensorFlow实现CNN

接着我们讲解如何在TensorFlow代码中编写CNN。之前我们用一般的神经网络来预测MNIST手写数字时,其准确率能达到87.78%。但该准确率相对目前的技术来说,是非常低的,我们需要编写CNN来实现,它能提升到96%左右。

第一步,打开Anaconda,然后选择已经搭建好的“tensorflow”环境,运行Spyder。

第二步,导入扩展包。

_data

第三步,下载数据集。
由于MNIST数据集是TensorFlow的示例数据,所以我们只需要下面一行代码,即可实现数据集的读取工作。如果数据集不存在它会在线下载,如果数据集已经被下载,它会被直接调用。

-------------------------------定义计算准确度函数------------------------------定义全局变量globalprediction比较预测最大值(y_pre)和真实最大值(v_ys)的差别如果等于就是预测正确,否则错误correct_prediction=((y_pre,1),(v_ys,1))输出结果为百分比百分比越高越准确result=(accuracy,feed_dict={xs:v_xs,ys:v_ys,keep_prob:1})returnresult

接着我们需要编写定义weight、bias、conv2d、max_pool_2x2等函数。

第五步,定义权重和误差变量。

输入shape返回变量定义的参数defweight_variable(shape):误差初始值定义为0.1initial=(0.1,shape=shape)(initial)

第六步,定义卷积神经网络层。

定义二维CNNx表示输入值或图片的值W表示权重defconv2d(x,W):strides:一个长度为4的列表第一个和最后一个元素为1第二个为元素是水平x方向的跨度第三个元素为垂直y方向跨度------------------------------------定义POOLING---------------------------------defmax_pool_2x2(x):x_movement和y_movement隔两个步长移动一次从而压缩整幅图片的长和宽_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')

第八步,定义placeholder,用于传入值xs和ys至神经网络。

每张图片28*28=784个点ys=(,[None,10])keepingprobabilitykeep_prob=()xs包括了所有的图片样本-1表示图片个数维度暂时不管(后续补充)[n_samples,28,28,1]

接下来我们就开始讲解如何添加神经层。

第九步,增加神经层conv1layer。

小方块的长度和宽度是5,insize为1是图片的厚度,输出的高度是32。

h_conv1输出的大小为282832,因为padding采用“SAME”的形式,W_conv1输出值为32,故厚度也为32,长度和宽度相同为28。而由于POOLING处理设置的strides步长为2,故其输出大小也有变化,其结果为141432。核心代码如下:

定义权重W_conv1=weight_variable([5,5,1,32])定义biasb_conv1=bias_variable([32])搭建CNN的第一层outputsize28*28*32outputsize14*14*32

第十步,通过同样的方法定义conv2layer。

W_conv2定义的patch为5*5,传入大小为32,传出大小为64,不断将其变厚,类似于下图所示。图片最早的厚度为1(MNIST数据集是黑白图片,如果是彩色则为3),接着第一层厚度变成32,第三层厚度增长为64。

此时h_conv2的输出结果为141464,第二层POOLING处理会继续缩小一半,h_pool2输出结果为7764,高度不变。

定义权重W_conv2=weight_variable([5,5,32,64])定义biasb_conv2=bias_variable([64])搭建CNN的第二层h_conv2=(conv2d(h_pool1,W_conv2)+b_conv2)POOLING处理h_pool2=max_pool_2x2(h_conv2)-------------------------------增加神经层func1layer------------------------------定义biasb_fc1=bias_variable([1024])将h_pool2输出值7*7*64转换为一维数据[n_samples,7,7,64]-[n_samples,7*7*64]h_pool2_flat=(h_pool2,[-1,7*7*64])乘法h_fc1=((h_pool2_flat,W_fc1)+b_fc1)-------------------------------增加神经层func2layer------------------------------定义biasb_fc2=bias_variable([10])预测值与真实值误差平均值-求和-ys*log(prediction)cross_entropyloss=_mean(-_sum(ys*(prediction),reduction_indices=[1]))训练学习学习效率设置为0.0001train_step=(1e-4).minimize(cross_entropyloss)定义Sessionsess=()提取一部分的xs和ysbatch_xs,batch_ys=_batch(100)训练(train_step,feed_dict={xs:batch_xs,ys:batch_ys})计算准确度print(compute_accuracy(,))

最终完整代码如下:

下载数据集数字1到10mnist=input__data_sets('MNIST_data',one_hot=True)参数:预测xs和预测ysdefcompute_accuracy(v_xs,v_ys):v_xs数据填充到prediction变量中生成预测值0到1之间的概率y_pre=(prediction,feed_dict={xs:v_xs,keep_prob:1})计算正确的数量accuracy=_mean((correct_prediction,))---------------------------------定义权重和误差变量------------------------------产生截断正态分布随机数initial=_normal(shape,stddev=0.1)(initial)defbias_variable(shape):---------------------------------定义卷积神经网络层------------------------------输入x表示整张图片的信息权重Wstrides表示步长跨度[1,x_movement,y_movement,1]padding包括两种形式VALID和(x,W,strides=[1,1,1,1],padding='SAME')Musthavestrides[0]=striders[3]=1-----------------------------定义placeholder输入至神经网络-------------------------每张图片28*28=784个点ys=(,[None,10])keepingprobabilitykeep_prob=()xs包括了所有的图片样本-1表示图片个数维度暂时不管(后续补充)[n_samples,28,28,1]定义权重W_conv1=weight_variable([5,5,1,32])定义biasb_conv1=bias_variable([32])搭建CNN的第一层outputsize28*28*32outputsize14*14*32定义权重W_conv2=weight_variable([5,5,32,64])定义biasb_conv2=bias_variable([64])搭建CNN的第二层h_conv2=(conv2d(h_pool1,W_conv2)+b_conv2)POOLING处理h_pool2=max_pool_2x2(h_conv2)-------------------------------增加神经层func1layer------------------------------定义biasb_fc1=bias_variable([1024])将h_pool2输出值7*7*64转换为一维数据[n_samples,7,7,64]-[n_samples,7*7*64]h_pool2_flat=(h_pool2,[-1,7*7*64])乘法h_fc1=((h_pool2_flat,W_fc1)+b_fc1)-------------------------------增加神经层func2layer------------------------------定义biasb_fc2=bias_variable([10])------------------------------定义loss和训练-------------------------------loss减小误差定义Sessionsess=()---------------------------------神经网络学习---------------------------------foriinrange(1000):从下载好的数据集提取100个样本每隔50步输出一次结果ifi%50==0:#计算准确度print(compute_accuracy(,))

接着运行代码,CPU基本上满负荷运转。

最终输出结果如下图所示,可以看到,最早预测的准确度结果非常低为6.78%,最后提升到了96.92%,其结果高于之前的一般神经网络的结果87.79%(第六篇博客),由此可见TensorFlowCNN的分类学习效果还不错。

0.06780.80960.88390.91190.92660.93610.94410.94960.95050.95610.95660.96160.96250.96440.96480.96680.96890.96980.97090.9692
三.总结

写到这里,这篇文章就结束了。本文详细介绍了卷积神经网络CNN的基本原理,并通过TensorFlow实现CNN卷积神经网络,结合MNIST手写体识别数据集进行分类学习。

最后,希望这篇基础性文章对您有所帮助,如果文章中存在错误或不足之处,还请海涵~作为人工智能的菜鸟,我希望自己能不断进步并深入,后续将它应用于图像识别、网络安全、对抗样本等领域,指导大家撰写简单的学术论文,一起加油!

读博不易,但深夜总喜欢挤时间写上一篇文章,算是对自己这么多年分享的鼓励,也希望自己能坚持,感谢家人的支持,小珞珞太可爱了。如果您也是从事Python数据分析、图像处理、人工智能、网络安全的朋友,我们可以深入探讨,尤其是做研究的同学,共同进步~

一.白话神经网络和AI概念入门普及

二.TensorFlow环境搭建、学习路线及入门案例

三.TensorFlow基础及一元直线预测案例

四.TensorFlow基础之Session、变量、传入值和激励函数

五.TensorFlow创建回归神经网络及Optimizer优化器

六.Tensorboard可视化基本用法及神经网络绘制

七.TensorFlow实现分类学习及MNIST手写体识别案例

八.什么是过拟合及dropout解决神经网络中的过拟合问题

九.卷积神经网络CNN原理详解及TensorFlow编写CNN

天行健,君子以自强不息。
地势坤,君子以厚德载物。

参考文献:

[1]神经网络和机器学习基础入门分享-作者的文章

[3]书籍《游戏开发中的人工智能》、《游戏编程中的人工智能技术》

[5]神经网络激励函数-deeplearning

[6]tensorflow架构-NoMorningstar

[7]Tensorflow实现CNN用于MNIST识别-siucaan

[8]MNIST手写体识别任务-chen645096127

[9]

[10]

[11]Google官方卷积神经网络介绍视频

你以为你有很多路可以选择,其实你只有一条路可以走

免责声明:本文章如果文章侵权,请联系我们处理,本站仅提供信息存储空间服务如因作品内容、版权和其他问题请于本站联系