深度学习三人行(第9期)----卷积神经网络实战进阶(附代码)

上一期,我们一起学习了深度学习中卷积神经网络的通俗原理,

深度学习三人行(第8期)----卷积神经网络通俗原理

接下来我们一起学习下关于CNN的代码实现,内存计算和池化层等相关知识,我们多多交流,共同进步。本期主要内容如下:

  • CNN实现(TensorFlow)
  • CNN之内存计算
  • CNN之池化层
  • 小结

公众号内回复关键字,即可下载代码,关键字见文末!


一. CNN实现(TensorFlow)

在TensorFlow中,每一个图像都有一个3D的tensor,shape为[height, width, channels]。每一个mini-batch是以一个shape为[min-batch size, height, width, channels]的4Dtensor来表示的。卷积层的权重是以shape为[f_h, f_w, f_n, f_n'],其中偏置项是以1D tensor[f_n]表示。接下来,我们一起看下,在TensorFlow中是怎么实现的:首先,代码中用sklearn中的load_sample_images()来加载图片。然后手工创建了两个7x7的卷积核,一个为水平直线,一个为竖直直线。接着让图像通过一个卷积层conv2d()(边界扩充0,stride = 2),最后画出一个特征图。如下:

 1import numpy as np
 2from sklearn.datasets import load_sample_images
 3# Load sample images
 4dataset = np.array(load_sample_images().images, dtype=np.float32)
 5batch_size, height, width, channels = dataset.shape
 6# Create 2 filters
 7filters_test = np.zeros(shape=(7, 7, channels, 2), dtype=np.float32)
 8filters_test[:, 3, :, 0] = 1 # vertical line
 9filters_test[3, :, :, 1] = 1 # horizontal line
10# Create a graph with input X plus a convolutional layer applying the 2 filters
11X = tf.placeholder(tf.float32, shape=(None, height, width, channels))
12convolution = tf.nn.conv2d(X, filters, strides=[1,2,2,1], padding="SAME")
13with tf.Session() as sess:
14    output = sess.run(convolution, feed_dict={X: dataset})
15plt.imshow(output[0, :, :, 1]) # plot 1st image's 2nd feature map
16plt.show()

其中X是一个mini-batch(4D的tensor),filters也是一个4D的tensor,stride是一个有4个元素的1D tensor其中中间连个值为竖直和水平的stride,第一个元素和第四个元素必须是1,这个是备用的,以后可能会用在batch和channel上。padding必须设置为“VALID”或“SAME”,当设为“VALID”的时候,卷积层不进行边界扩充,但是可能会根据stride来忽略图像下面的某些行或右侧的某些列。如果设置为“SAME”,卷积层会进行对边界扩充0.这种情况下,输出神经元个数等于输入神经元个数除以stride,在下面的例子中输出层神经元为3,其中stride为5.如下:

所以,卷积层有一些参数要设置,比如:卷积核的个数,卷积核的高,卷积核的宽,以及stride,padding的类型。有时候,可以通过交叉验证来找最优的参数组合,但是这样往往是比较耗时的。后面我们会介绍一些通用的网络结构,可能会给我们一些启发,在实践中什么样的参数组合通常会得出最优的性能。


二. CNN之内存计算

卷积神经网络的一个问题就是需要大量的内存来处理数据,特别是在training阶段,因为反向传输需要保留前向传输的数据。举个例子,比方一个卷积层,其中卷积核为5x5,输出200个特征图,每一个特征图大小为150x100, stride为1,padding为"SAME",如果输入为一个150x100的RGB(3通道)图像的话,那么权重参数的个数为:

(5x5x3+1)x200 = 15200

其中+1为考虑到偏置项,相对来说,参数比全连接层要少。然而,每一个特征图包括150x100个神经元,每一个神经元需要计算5x5x3=75个权重,那么总共就有225million个浮点型数据相乘,虽然没有比全连接更糟,但是仍然是一个巨大的计算。如果特征图用32位float表示的话,那么一个卷积层将会占用:

200x150x100x32 = 96million bits

约11.4M内存,然而这只是一个样本,如果每个batch有100张图的话,那么单单这一层卷积层就要耗费超过一个G的内存。

在预测的时候,当一个卷积层计算的时候,就会将上一层所占用的内存释放掉,所以仅仅需要两个连续卷积层所占的内存即可。但是在计算的时候,每一次向前传输的数据都要为向后传输而保留,所以所需要的内存至少为全部层所占用的内存总和。

如果在training的时候,由于内存的问题导致crash,那么可以通过减少mini-batch的size来进行降低内存占有。当然也可以通过stride降维,或者减少一些层,甚至可以用16bit的float代替32bit的float或者多个设备来跑。

接下来,我们一起看一下CNN的另一个重要的构成:池化层。


三. CNN之池化层

一旦我们理解了卷积层的工作原理之后,池化层就相对来说比较简单了,池化层的目标就是为了降低计算负载,内存使用,参数数量,也可以降低过拟合的风险,而对输入进行的下采样。原理和卷积层一样,池化层的每一个神经元和上一层中有限区域(一个矩形的感受野)的神经元相连接。我们也必须定义感受野的size, stride,以及padding类型。然而不同的是,池化层的神经元没有权重,它的输出仅仅是输入区域的最大值或均值,下图显示了一个最大值的池化层,也是最常用的池化层,这个例子中用了一个2x2的池化核,stride=2,没有padding,也就是说,仅仅输出上一层中池化核位置的最大值到下一层。其他的输入都丢掉。

一般池化层在每一个输入通道上单独工作,所以经过池化层后,输入输出通道数不变。

在TensorFlow中实现池化还是蛮简单的,下面的代码创建一个2x2的池化核的池化层,stride为2,没有padding,然后应用到所有图像上。

1[...] # load the image dataset, just like above
2# Create a graph with input X plus a max pooling layer
3X = tf.placeholder(tf.float32, shape=(None, height, width, channels))
4max_pool = tf.nn.max_pool(X, ksize=[1,2,2,1], strides=[1,2,2,1],padding="VALID")
5with tf.Session() as sess:
6    output = sess.run(max_pool, feed_dict={X: dataset})
7plt.imshow(output[0].astype(np.uint8)) # plot the output for the 1st image
8plt.show()

上面参数ksize包括了池化核的4D参数[batch size, height, width, channels].TensorFlow目前暂时不支持跨样本池化,所以第一个数据必须是1,由于目前也不支持跨通道池化,所以最后一个参数也得是1.当然,想创建一个均值的池化层的话,仅仅将上面的max_pool替换为avg_pool即可。


四. 小结

今天,我们从TensorFlow上实现卷积层,以及卷积层的内存计算和池化层的相关原理知识等方面,更进一步的了解了CNN的知识。在学习的路上,我们共同进步,多谢有你。

原文发布于微信公众号 - 智能算法(AI_Algorithm)

原文发表时间:2018-11-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏和蔼的张星的图像处理专栏

4. 经典卷积网络之AlexNet

原文:《ImageNet Classification with Deep Convolutional Neural Networks》 我没有读原文,这个已...

18220
来自专栏CNN

Tensorflow反卷积(DeConv)实现原理+手写python代码实现反卷积(DeConv)

上一篇文章已经介绍过卷积的实现,这篇文章我们学习反卷积原理,同样,在了解反卷积原理后,在后面手写python代码实现反卷积。

34730
来自专栏邹成卓的专栏

三维变换矩阵的理解

3D空间中的一个点的坐标,可以用(x,y,z)来表示。对这个点的坐标变换有三种操作:缩放、平移、旋转。

2.1K20
来自专栏宏伦工作室

动手实现notMNIST数据集图片分类

21230
来自专栏深度学习之tensorflow实战篇

SVM:利用sklearn 实现SVM分类 相关参数说明ING

scv 函数 class sklearn.svm.SVC(C=1.0, kernel=’rbf’, degree=3, gamma=’auto’, coef0...

31370
来自专栏AI科技评论

深度丨机器学习零基础?手把手教你用TensorFlow搭建图像识别系统(三)

AI科技评论按:本文是介绍用TensorFlow构建图像识别系统的第三部分。 在前两部分中,我们构建了一个softmax分类器来标记来自CIFAR-10数据集的...

38860
来自专栏人工智能LeadAI

Tensorflow之 CNN卷积神经网络的MNIST手写数字识别

前言 tensorflow中文社区对官方文档进行了完整翻译。鉴于官方更新不少内容,而现有的翻译基本上都已过时。故本人对更新后文档进行翻译工作,纰漏之处请大家指正...

66250
来自专栏机器学习原理

深度学习——LeNetLeNet解析

21340
来自专栏菩提树下的杨过

WPF中的MatrixTransform

WPF中的MatrixTransform            周银辉 虽然在WPF中可以使用TranslateTransform、RotateTrans...

217100
来自专栏求索之路

cs231n之KNN算法

1.环境搭建以及前置条件 1.前置环境: 1.mac 2.pycharm 3.python3 4.Anaconda 2.环境搭建: 1.官网下载并安装Ana...

35690

扫码关注云+社区

领取腾讯云代金券