(mxnet)卷积神经网络一:LeNet

本专题全是用manet实现的,书籍是动手学深度学习,我想换个角度来分析卷积神经网络,最后有对应的论文和我写的源码,都在我的GIthub上。
接下来的文章中都分为三个问题:解析网络结构,使用的一些技巧,一些总结。当然会有一些自问自答的环节,希望可以尽量清除描述别人的工作(有不同的观点请留言哈)。
图片来自于论文,阅读它可以加强理解。

1 卷积神经网络解决的问题?

答:我想有两个主要的问题。

  1. 对图像而言,保留相邻像素在垂直水平方向的信息(保留两个方向上的相关性),比如如果我们将一张图像拉成行向量,势必会丢失垂直方向上的信息,而深度卷积网络输入的是图像,这一点是人们希望的。
  2. 对于大尺寸的图像,全连接层极容易造成模型过大,占用大量的显存和计算资源。比如,310001000图像,全连接Dense(256),将会占3G显存,这是低效的。通过卷积核可以很好的避免这个问题(深度网络最出彩的就是卷积)。

2 如何比较深刻的了解一个网络?

我觉得至少在学习后,可以大致的把结构讲出来,包括
这个网络有多少层?
用了什么块结构?有什么特点?输入的是什么,输出的是什么?
每层的kernel_size, pool_size, padding, strides
网络有什么特点?
有没有一些trick?

3 LeNet网络结构

在这里插入图片描述

  1. LeNet网络结构比较简单,我们可以划分成三个大块,如图所示,不妨认为是块1, 块2,块3。块1表示一个卷积+一个最大池化,同理块2也是这样的,块三是连续三个全连接层。
  2. 激活函数是sigmoid,现在relu用的多,因为sigmoid接近0或1有梯度消失和爆炸的情形
  3. 深度网路是一系列卷积池化堆叠起来的,其中还有一个重要的思想就是模块化操作,正如块1,块2是一摸一样,这也是搭建复杂网络的一个手段(简单的块堆叠)。

在这里插入图片描述
上面两个图表示这个结构的框架,第二张图是MxNet的表示,也很形象。接着再进一步分析下。

3.1 LeNet简析

由于是第一次,我会把基本概念简单的重复下,不过我建议,看看《动手学深度学习》第五章106-120页,下面是开源电子书
http://zh.d2l.ai/chapter_convolutional-neural-networks/conv-layer.html

3.2 基本术语

  1. 网络层数: 卷积层的个数+全连接层。池化层是紧贴最近一个卷积层,不考虑它。这里的话就是1+1+3=5哈
  2. padding(填充):矩阵有四条边,一般情况下补的是0,理论上pdding有四种。举个例子,5*3的矩阵在右边补了一列0,变成5*4。但是为了计算方便,默认左右补的个数一样,同理上下补的个数也一样,注意:而且进一步,四个方向补的个数都一样,这样也就是补了多少圈零,这是默认的意思,代码中默认为0,即不周围补0
  3. stride(步幅): 有两个方向,不妨记横着每次跨步为 s w s_w sw, s竖着每次跨步为 s h s_h sh

为了计算方便,记左右补0总数为 p w p_w pw, 记上下补0总数为 p h p_h ph,让我们看看padding和stride的物理意义。

  1. 输入补[ p w p_w pw, p h p_h ph],输出的宽和高对应增加 p w p_w pw, p h p_h ph
  2. stride可以以stride倍减少输入尺寸,举例,输入10*10,stride=5,输出2*2。当然有准确的输入到输出计算公式,这里只是比方以stride倍减少。注意:降低模型的复杂度,也是stride存在的意义

重要结论,输入尺寸,padding,stride,输出尺寸的数学表达式
⌊ ( n h − k h + p h + s h ) / s h ⌋ × ⌊ ( n w − k w + p w + s w ) / s w ⌋ \lfloor(n_h-k_h+p_h+s_h)/s_h\rfloor \times \lfloor(n_w-k_w+p_w+s_w)/s_w\rfloor (nhkh+ph+sh)/sh×(nwkw+pw+sw)/sw
上面符号是向下取整,很明显可以看出, s w s_w sw s h s_h sh在分母上。
其中
n h n_h nh, n w n_w nw表示高,宽;
k h k_h kh, k w k_w kw表示卷积核高,宽,进一步卷积核取奇数且是正方形的
**还要注意的是, p h p_h ph, p w p_w pw是上下,左右总和,而padding只是一边的,所以 p h p_h ph=2padding, p w p_w pw=2padding, **
接下来很多网路都要用到,用到麻木为止。

3.3 逐层解析

我补充了3.2节,不然我觉得既浪费你的时间,也浪费我的时间。
看图说话,
块1的卷积层,输入32*32,输出6@28*28,想想padding,kernel_size,strides是多少
不难看出减少了4*4,不妨分析一个方向。

  1. 显然strides=1,不为1的话,会以strides倍较少,若为2,结果接近16*16,显然不可能
  2. 进而-kernel_size+2*0+1=4, 显然kernel_size=5,符合预期的奇数
  3. 为什么断定padding=0,因为不告诉你默认是0,这是代码的默认行为padding=0,strides=1,不要补,一步一步走

块1的池化层输入6@28*28,输出6@14*14
4. 显然寸尺减半,strides=2, 也就是(28-2+2*0+2)/2=14
5. 池化层用pool_size代替kernel_size,实质一样的,上面的公式同样适用

块2的卷积层,池化层, 发现卷积层减少4,池化层减半,也就是和块1的参数一摸一样
三个全连接层,全连接层只有一超参,神经元的个数,这里分别是120,84,10(10分类,直接和问题挂钩),至于120,84想怎么改就怎么改,还可以去掉120层或84层或全去掉,反正提高test acc。
案例输出:符合预期(下面输入的28*28,数据集不一样),也当一个练习啦

# 一个样本测试(1*1*28*28)
X = nd.random.uniform(shape=(1, 1, 28, 28))
net.initialize()
for layer in net:
    X = layer(X)
    print(layer.name, 'output shape:\t', X.shape)

在这里插入图片描述

3.4 更进一步

我么看看上面的结果,可以认为池化和最靠近的卷积是一层。这样的话,看看pool0,conv1,pool2, dense0

  1. pool0: 6*12*12=864
  2. conv1: 16*8*8=1024
  3. 这两个数值相差不大,举个例子,两个若相等,则第二层通道数是13.5,接下来调参。
  4. pool1: 16*4*4-256
  5. dens0:120
  6. 同理这两个相差也不大
    之前,一直没解释通道数这个超参,既然是超参,就没有严格的理论支持,有一些经验。
    从上面可以发现,尺寸变小,其通道数会增大,这一点是多数是符合的,但是增加多少,那就要调参了,不过一个初始的想法就是让相邻层变化不大,正如上面的描述。

4 总结

最重要的东西
⌊ ( n h − k h + p h + s h ) / s h ⌋ × ⌊ ( n w − k w + p w + s w ) / s w ⌋ \lfloor(n_h-k_h+p_h+s_h)/s_h\rfloor \times \lfloor(n_w-k_w+p_w+s_w)/s_w\rfloor (nhkh+ph+sh)/sh×(nwkw+pw+sw)/sw

  1. 输入补[ p w p_w pw, p h p_h ph],输出的宽和高对应增加 p w p_w pw, p h p_h ph
  2. stride可以以stride倍减少输入尺寸,举例,输入10*10,stride=5,输出2*2。当然有准确的输入到输出计算公式,这里只是比方以stride倍减少。注意:降低模型的复杂度,也是stride存在的意义
  3. 尺寸变小,其通道数会增大,这一点是多数是符合的
  4. 简单块的堆叠是实现复杂网络的一个手段

5 源码和论文

欢迎访问我的Giuhub,
https://github.com/ve2102388688/myMXNet

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值