【CNN模型笔记(二)】AlexNet模型+代码实现

由于受到计算机性能的影响,虽然LeNet在图像分类中取得了较好的成绩,但是并没有引起很多的关注。 知道2012年,Alex等人提出的AlexNet网络在ImageNet大赛上以远超第二名的成绩夺冠,卷积神经网络乃至深度学习重新引起了广泛的关注。

AlexNet创新点:

  • 成功应用ReLU激活函数
  • 成功使用Dropout机制
  • 使用了重叠的最大池化(Max Pooling)。此前的CNN通常使用平均池化,而AlexNet全部使用最大池化,成功避免了平均池化带来的模糊化效果
  • 提出LRN(局部响应归一化)
  • 使用GPU加速训练
  • 使用了数据增强策略(Data Augmentation)

1.ReLU

针对sigmoidsigmoid梯度饱和导致训练收敛慢的问题,在AlexNet中引入了ReLU。ReLU是一个分段线性函数,小于等于0则输出为0;大于0的则恒等输出。相比于sigmoidsigmoid,ReLU有以下有点:

  • 计算开销小。sigmoidsigmoid的正向传播有指数运算,倒数运算,而ReLu是线性输出;反向传播中,sigmoidsigmoid有指数运算,而ReLU有输出的部分,导数始终为1.
  • 梯度饱和问题
  • 稀疏性。Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生

2.数据增强

神经网络由于训练的参数多,表能能力强,所以需要比较多的数据量,不然很容易过拟合。当训练数据有限时,可以通过一些变换从已有的训练数据集中生成一些新的数据,以快速地扩充训练数据。对于图像数据集来说,可以对图像进行一些形变操作:

  • 翻转
  • 随机裁剪
  • 平移,颜色光照的变换
  • ...

AlexNet中对数据做了以下操作:

  1. 随机裁剪,对256×256256×256的图片进行随机裁剪到227×227227×227,然后进行水平翻转。
  2. 测试的时候,对左上、右上、左下、右下、中间分别做了5次裁剪,然后翻转,共10个裁剪,之后对结果求平均。
  3. 对RGB空间做PCA(主成分分析),然后对主成分做一个(0, 0.1)的高斯扰动,也就是对颜色、光照做变换,错误率下降1%

3.层叠池化

在LeNet中池化是不重叠的,即池化的窗口的大小和步长是相等的,如下

在AlexNet中使用的池化(Pooling)却是可重叠的,也就是说,在池化的时候,每次移动的步长小于池化的窗口长度。AlexNet池化的大小为3×3的正方形,每次池化移动步长为2,这样就会出现重叠。重叠池化可以避免过拟合,这个策略贡献了0.3%的Top-5错误率。与非重叠方案s=2,z=2s=2,z=2相比,输出的维度是相等的,并且能在一定程度上抑制过拟合。

4.LRN(局部响应归一化)

论文内容如下:

功能:

  • LRN函数类似DROPOUT和数据增强作为relu激励之后防止数据过拟合而提出的一种处理方法
  • LRN对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。

参数含义:

对局部响应归一化的理解

5.Dropout策略

这个是比较常用的抑制过拟合的方法了。
引入Dropout主要是为了防止过拟合。在神经网络中Dropout通过修改神经网络本身结构来实现,对于某一层的神经元,通过定义的概率将神经元置为0,这个神经元就不参与前向和后向传播,就如同在网络中被删除了一样,同时保持输入层与输出层神经元的个数不变,然后按照神经网络的学习方法进行参数更新。在下一次迭代中,又重新随机删除一些神经元(置为0),直至训练结束。
Dropout应该算是AlexNet中一个很大的创新,现在神经网络中的必备结构之一。Dropout也可以看成是一种模型组合,每次生成的网络结构都不一样,通过组合多个模型的方式能够有效地减少过拟合,Dropout只需要两倍的训练时间即可实现模型组合(类似取平均)的效果,非常高效。
如下图:

AlexNet网络结构

【注】卷积结果计算公式:

输入图像的大小为nxn,卷积核的大小为mxm,步长为s, 为输入图像两端填补p个零(zero padding),那么卷积操作之后输出的大小为(n-m+2p)/s + 1

 

上图中的输入是224×224224×224,不过经过计算(224−11)/4=54.75(224−11)/4=54.75并不是论文中的55×5555×55,而使用227×227227×227作为输入,则(227−11)/4=55

网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层。最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000类标签的分布网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层。最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000类标签的分布。

  • 卷积层C1
    该层的处理流程是: 卷积-->ReLU-->池化-->归一化。
    • 卷积,输入是227×227227×227,使用96个11×11×311×11×3的卷积核,得到的FeatureMap为55×55×9655×55×96。
    • ReLU,将卷积层输出的FeatureMap输入到ReLU函数中。
    • 池化,使用3×33×3步长为2的池化单元(重叠池化,步长小于池化单元的宽度),输出为27×27×9627×27×96((55−3)/2+1=27(55−3)/2+1=27)
    • 局部响应归一化,使用k=2,n=5,α=10−4,β=0.75k=2,n=5,α=10−4,β=0.75进行局部归一化,输出的仍然为27×27×9627×27×96,输出分为两组,每组的大小为27×27×4827×27×48
  • 卷积层C2
    该层的处理流程是:卷积-->ReLU-->池化-->归一化
    • 卷积,输入是2组27×27×4827×27×48。使用2组,每组128个尺寸为5×5×485×5×48的卷积核,并作了边缘填充padding=2,卷积的步长为1. 则输出的FeatureMap为2组,每组的大小为27×27 times12827×27 times128. ((27+2∗2−5)/1+1=27(27+2∗2−5)/1+1=27)
    • ReLU,将卷积层输出的FeatureMap输入到ReLU函数中
    • 池化运算的尺寸为3×33×3,步长为2,池化后图像的尺寸为(27−3)/2+1=13(27−3)/2+1=13,输出为13×13×25613×13×256
    • 局部响应归一化,使用k=2,n=5,α=10−4,β=0.75k=2,n=5,α=10−4,β=0.75进行局部归一化,输出的仍然为13×13×25613×13×256,输出分为2组,每组的大小为13×13×12813×13×128
  • 卷积层C3
    该层的处理流程是: 卷积-->ReLU
    • 卷积,输入是13×13×25613×13×256,使用2组共384尺寸为3×3×2563×3×256的卷积核,做了边缘填充padding=1,卷积的步长为1.则输出的FeatureMap为13×13 times38413×13 times384
    • ReLU,将卷积层输出的FeatureMap输入到ReLU函数中
  • 卷积层C4
    该层的处理流程是: 卷积-->ReLU
    该层和C3类似。
    • 卷积,输入是13×13×38413×13×384,分为两组,每组为13×13×19213×13×192.使用2组,每组192个尺寸为3×3×1923×3×192的卷积核,做了边缘填充padding=1,卷积的步长为1.则输出的FeatureMap为13×13 times38413×13 times384,分为两组,每组为13×13×19213×13×192
    • ReLU,将卷积层输出的FeatureMap输入到ReLU函数中
  • 卷积层C5
    该层处理流程为:卷积-->ReLU-->池化
    • 卷积,输入为13×13×38413×13×384,分为两组,每组为13×13×19213×13×192。使用2组,每组为128尺寸为3×3×1923×3×192的卷积核,做了边缘填充padding=1,卷积的步长为1.则输出的FeatureMap为13×13×25613×13×256
    • ReLU,将卷积层输出的FeatureMap输入到ReLU函数中
    • 池化,池化运算的尺寸为3×3,步长为2,池化后图像的尺寸为 (13−3)/2+1=6(13−3)/2+1=6,即池化后的输出为6×6×2566×6×256
  • 全连接层FC6
    该层的流程为:(卷积)全连接 -->ReLU -->Dropout
    • 卷积->全连接: 输入为6×6×2566×6×256,该层有4096个卷积核,每个卷积核的大小为6×6×2566×6×256。由于卷积核的尺寸刚好与待处理特征图(输入)的尺寸相同,即卷积核中的每个系数只与特征图(输入)尺寸的一个像素值相乘,一一对应,因此,该层被称为全连接层。由于卷积核与特征图的尺寸相同,卷积运算后只有一个值,因此,卷积后的像素层尺寸为4096×1×14096×1×1,即有4096个神经元。
    • ReLU,这4096个运算结果通过ReLU激活函数生成4096个值
    • Dropout,抑制过拟合,随机的断开某些神经元的连接或者是不激活某些神经元
  • 全连接层FC7
    流程为:全连接-->ReLU-->Dropout
    • 全连接,输入为4096的向量
    • ReLU,这4096个运算结果通过ReLU激活函数生成4096个值
    • Dropout,抑制过拟合,随机的断开某些神经元的连接或者是不激活某些神经元
  • 输出层
    第七层输出的4096个数据与第八层的1000个神经元进行全连接,经过训练后输出1000个float型的值,这就是预测结果。

AlexNet代码实现

参考《深度学习之美》实现了基于MNIST的AlexNet网络结构

#coding:utf-8
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data',one_hot=True)
sess = tf.InteractiveSession() #在运行之前先定义一些操作,Session必须在所有操作全部定义完才能是运行

#初始化权值和偏重
def weight_variabe(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)#产生截断的正态分布张量,shape表示产生的张量维度,mean为均值,stddev为标准差
    return tf.Variable(initial)

def bias_variable(shape):
    initial = tf.constant(0.1, shape = shape)
    return tf.Variable(initial)

#卷积和池化层实现
def conv2d(x,W):
    return tf.nn.conv2d(x,W, strides = [1,1,1,1], padding = 'SAME')

def max_pool_3x3(x):
    return tf.nn.max_pool(x,ksize = [1,3,3,1],strides = [1,2,2,1], padding = 'SAME')

#LRN  局部响应归一化层
def norm(x,lsize = 4):
    return tf.nn.lrn(x,lsize,bias = 1.0,aplha = 0.001/9.0 ,beta = 0.75)

#构建卷积层
x = tf.placeholder(tf.float32, [None,784])
y_ = tf.placeholder(tf.float32,[None,10])
keep_prob = tf.placeholder(tf.float32)
x_image = tf.reshape(x,[-1,28,28,1])

W_conv1 = weight_variabe([3,3,1,64])
b_conv1 = bias_variable([64])
h_conv1 = tf.nn.relu(conv2d(x_image,W_conv1) + b_conv1)
h_pool1 = max_pool_3x3(h_conv1)
h_norm1 = norm(h_pool1, lsize=4)

W_conv2 = weight_variabe([3,3,64,128])
b_conv2 = bias_variable([128])
h_conv2 = tf.nn.relu(conv2d(h_norm1,W_conv2) + b_conv2)
h_pool2 = max_pool_3x3(h_conv2)
h_norm2 = norm(h_pool2, lsize=4)

W_conv3 = weight_variabe([3,3,128,256])
b_conv3 = bias_variable([256])
h_conv3 = tf.nn.relu(conv2d(h_pool2,W_conv3) + b_conv3)
h_pool3 = max_pool_3x3(h_conv3)
h_norm3 = norm(h_pool3, lsize=4)

#实现全连接和Dropout
W_fc1 = weight_variabe([3,3,128,256])
b_fc1 = bias_variable([1024])
h_norm3_flat = tf.reshape(h_norm3,[-1,4*4*256])
h_fc1 = tf.nn.relu(tf.matmul(h_norm3_flat,W_fc1) + b_fc1)
h_fc1_drop = tf.nn.dropout(h_fc1,keep_prob)

W_fc2 = weight_variabe([1024,1024])
b_fc2 = bias_variable([1024])
h_fc2 = tf.nn.relu(tf.matmul(h_fc1_drop,W_fc2) + b_fc2)
h_fc2_drop = tf.nn.dropout(h_fc2 , keep_prob)

#实现Readout层
W_fc3 = weight_variabe([1024,0])
b_fc3 = bias_variable([10])
y_conv = tf.matmul(h_fc2_drop,W_fc3) +b_fc3

#参数训练与模型评估
cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(labes = y_,logits=y_conv)
)
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1),tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

sess.run(tf.global_variables_initializer())
for i in range(20000):
    batch = mnist.next_batch(50)
    if i%100 == 0:
        train_accuracy = accuracy.eval(feed_dict={
            x:batch[0] , y_:batch[1] , keep_prob:1.0
        })
        print('step %d,training accuracy %g'%(i,train_accuracy))
    train_step.run(feed_dict = {x:batch[0], y_:batch[1] , keep_prob : 0.5})

print('test accuracy %g'% accuracy.eval(feed_dict = {
    x:mnist.test.images, y_:mnist.test.labels , keep_prob:1.0
}))
sess.close()

【参考】

《深度学习之美》

CNN经典结构汇总:https://www.cnblogs.com/liaohuiqiang/p/9606901.html

AlexNet网络结构:https://www.cnblogs.com/wangguchangqing/p/10333370.html

  • 10
    点赞
  • 165
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wimb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值