卷积神经网络——传统卷积网络和残差网络

这是吴恩达老师的第二部分视频的学习笔记

大致讲解了在神经网络的发展历史上,出现过lenet,alexnet,VGG,ResNet,Inception这些网络。我们在实现自己的网络架构的时候,尽量不要瞎想,而是要参考前人的网络架构。

首先介绍了LeNet的网络架构。当时使用了averge_pooling,现在更常使用的是 ** x_pooling。当时使用的非线性函数主要是sigmoid和tanh以及relu,现在使用soft ** x也比较多(这里不是很确定)。当时的计算机计算速度并没有很快,因此在Lenet的论文中提到了很多精妙的优化速度的手段,但是现在基本不用了。因此再读那篇论文的时候,应该精读第二部分,泛泛的读第三部分即可。

AlexNet的网络结构如下图所示,和lenet类似,但是这里的参数数量有6000万之多。AlexNet的性能要比LeNet好,原因是这里使用了更多的参数更加复杂的网络,同时使用了ReLu作为激活函数。在Alexnet的论文中,还提到了Local Response Nor ** lization,这个操作的含义是将贯穿不同信道同一位置的节点们归一化处理,据原论文说这样可以减少高激活神经元,但是后来的研究发现这样做并没有什么特别大的好处。

VGG网络优秀的在于真正简化了神经网络的结构,虽然VGG-16有16层,还是比较深的网络,参数也有13600万之多。但是这个网络优美的表现出了“长宽缩减的比例和信道增加的比列”相关的信念。在这个网络中,始终使用3*3的filter,每次使用same conv的模式;输入每经过一轮(一轮可能是2-3个卷积层)过滤器,channel数量增加一倍。池化层始终使用 ** x pooling,且每经过一次池化层,长宽缩小一半。最后使用了两个全连接层和一个最终输出层。

吴恩达老师推荐我们看论文的顺序是先AlexNet,然后VGG,最后LeNet。LeNet的内容比较晦涩难懂。

普通的神经网络,随着网络的深度增加会存在梯度爆炸和梯度消失等问题,变得越来越难以训练。残差网络的提出使得训练深度网络变得更加容易。他的原理是在某一层的线性模块之后,非线性模块之前增加前面某曾的输出,(这种操作又被称为skip connection),使得该层的非线性层a^(l+1) =g(z^l +a^(l-n)).这样的n个块被称为一个残差块。如下图所示的网络中一共有5个残差块。

网络只有在训练集上训练好才能在hold-out 交叉验证集上效果好。从经验来看,传统的网络存在随着深度的加深,学习的效率会逐步下降的缺点。但是对于残差网络来说,增加两层之后的恒等函数很容易学习。参考阅读这篇博客,暂时还没有看懂,希望下次巩固的时候可以看懂。

一般情况下,a^(l+2) 和 a^l 的维度是一致的,因为残差网络中一般使用same的卷积,偶尔会使用池化层。当a^(l+2) 和 a^l 的维度不一致时(池化层),可在a^l前面乘以一个W矩阵,保持维度的一致性。

1 * 1卷积对于单信道输入来说,只是将对应位置乘以对应的值而已。但是对于多信道输入而言,一个1 * 1卷积过滤器相当于将同一位置多个信道的元素加权相加,相当于一个全连接操作,之后会通过一个非线性函数操作,也就是相当于组合了同一位置的所有信道的元素,使其增加了非线性能力。

当输入的信道数量太多时,可以通过1 * 1卷积进行压缩信道(当然也可以增加信道,通过控制过滤器的数量),并且不改变height和weight(改变这两个参数的方式是池化层).这个1 * 1卷积的思想对于Inception网络很有用。

Inception网络可以让我们避免自己去人工构建卷积层或者池化层。而是自己去学习到底使用什么卷积层或者是池化层。

其实现的原理就是把1 * 1卷积、3 * 3卷积、5 * 5卷积以及池化层的结果都叠加在一起共同作为这一层的输出,然后让网络自行去学习参数。(注意思考为什么图中的最大池化层的输出channel数量是32?我还没有理解,按理来说池化层的输出channel数量应该保持不变才对)

可以想象,这样的网络计算成本非常大 。以其中一个 5 * 5卷积来说。为了构建一个 28 * 28 *32的输出层,需要进行的乘法操作如下:对于每个输出的元素都需要进行 5 * 5 *192的乘法操作。这样的乘法操作数量达到了120Million次。

因此Inception使用1 * 1卷积构建一个瓶颈层来减少计算量(可以将计算量减小为曾经的十分之一)。通过合理的构建一个中间层。

通过上面提到的两个思想,可以构建Inception模块。Inception模块中既使用了 1 * 1卷积构建瓶颈层来减小计算量,又使用了多种卷积方式让其自我学习。

注意到最后的池化层实际上是一个池化层加上一个1 * 1的卷积层来控制channel数量的。

一个Inception网络就是由众多Inception模块构成的。其中的红色模块是池化层,用于减少长宽。底部有一些分支,这些分支实际上是使用隐藏层来做全连接、最后实现soft ** x预测。这意味着即使是中间的隐藏层也可以做预测,这些模块起到了一个调整的作用,避免整个网络过拟合。

上面这张图也被称为Googlenet,为了致敬LeNet网络。

自己训练网络是一件耗时耗CPU的痛苦的经历。github上有很多公共的神经网络代码以及设计好的网络架构和权重,我们可以利用这些网络来初始化我们的专用需求。

当我们自己只有少量的数据时,我们可以固定他人网络的所有隐藏层,只修改soft ** x层来适应自己的需求。为了减少计算量,来可以将自己的数据运行到soft ** x层之前的都保存起来当做input,只经过soft ** x,这样训练的速度就很快。

当我们的数据量不那么少的时候,可以固定前面的隐藏层,留下一两个隐藏层以及soft ** x层做训练。

当我们的数据量比较多的时候,可以将他人网络的权重作为初始值,然后训练整个网络。

一般的网络框架都会有可以固定前面隐藏层的参数的。

计算机视觉神经网络面对的一个大问题是数据不充足。常见的数据增强的方式有

颜色偏移,一般对RGB三信道的数值按照某种分布做微小的调整得到不同的图片。这种变化是基于有时候光线的变化不应该对最终的标签有影响。这种变换可以增加对光线的鲁棒性。 当我们的数据量比较多的时候,通常会这样实现数据增强。使用一个或者多个线程来持续读取并转换数据(将数据通过不同的方式转换),构成一个batch的图片,然后输入另一个训练线程。图片增强和训练的过程可以并行执行。

数据增强的过程同样有很多的超参数,比如颜色变化的分布参数等。因此我们也可以使用别人的开源实现。

当我们在计算机视觉使用神经网络的时候,我们的目的有两个1. 参加比赛获得好的名次; 2.实际应用部署赚钱。

对于第一个目标,建议有两个:

对于第二个目标的建议就是使用别人以后的网络作为初始化。因为别人可能把比较困难的痛苦细节都帮你完善好了。

© 版权声明
THE END
喜欢就支持以下吧
点赞10
分享
相关推荐
  • 暂无相关文章
  • 评论 抢沙发
    源码客的头像-源码客

    昵称

    取消
    昵称表情图片