4.2 深度卷积:实例探究

 

为找到效果良好的神经网络,参考别人的网络是最好的方法。实际上,在计算机视觉任务中表现良好的神经网络框架往往也适用于其他任务。

经典网络:

 

 

 

 

 

残差网络

 

如图是两个全连接层,中间蓝色字体的写出的是正向传播的过程,注意这里吴恩达把计算z的那一步称为线性激活,a称为非线性激活,本质与以前学的一样。此时如果将第一层的输入再通过紫色路径加到第二次的线性激活后非线性激活前那个位置,那么最后一个非线性激活公式中再加一个a的项,就构成了一个残差块。注意,原先的全连接的计算没有省去,而是在一个位置加了一部分。吴恩达用了一些a直达第二层的捷径,或者“远跳连接”之类的词描绘,将a的信息传递到更深层的网络。研究者们发现这种方式能够训练更深层的网络(注意,因为梯度消失和梯度爆炸的问题,训练很深层的网络是非常困难的,残差网络的出现就是为了解决训练深层网络的问题)。

构建一个ResNet网络就是将很多这样的残差块堆积在一起,形成一个很深的网络。

理论上说,网络的深度越深,应该训练的越来越好才对。但是实际上随着网络层数的加大,训练错误也逐渐增多。而加入ResNet以后,我们可以训练非常深的网络而不会出现这种问题。

 

为什么残差网络有用?

如图第一行假如是一个很大的神经网络,然后第二行给这个网络加了一个残差块,我们看看最后一个输出a的公式展开,如果我们使用Relu函数激活,并且又使用了正则化,那么a[L]就有可能被衰减的非常小,几乎为0,再假设b为0。那a[L+2]就几乎等于g(a[L]),也就是说学习到了一个恒等函数。吴恩达认为残差网络起作用的主要原因就是残差块学习恒等函数非常容易。如果这个网络学习到了一些有用的信息,那么它的参数不会为0,它就可以发挥它的作用。这里说的是如果这一层并没有学习到什么有用的信息,那就可以当作他不存在。但是普通的神经网络很难做到这一点,所以很多层以后的表现很可能变得更糟。

另外,如果残差块的输入和输出是同一个维度那没有问题,如果维度不同,显然最后那个公式加a[L]的时候会因为维度不对出现问题,那么就再a[L]之前再加一个Ws(输出维度x输入维度)矩阵,将a[L]转换为和输出相同的维度,这个Ws是通过学习而得到的参数,无需手工设置。

 

1x1卷积

 

一个1x1的卷积乍一听没什么作用,只是将输入的所有像素乘了一个系数。但当输入图像的信道很多时,就有意义了。如图,这就相当于把一个位置在所有信道上的一条数据取出来,各自乘以一个系数然后再经过ReLU函数,就相当于将这一条32个数据输入进一个神经元,乘以参数。那么更一般的,我们都会采用很多个过滤器,就相当于32个输入进入不同的神经元乘以不同的参数再进行非线性激活,那其实就可以看作是普通神经网络的全连接层。你可以通过设置过滤器的数量来控制输出的数据有多少个信道,那么其实1x1卷积还可以用来压缩信道数量(之前讨论过随着网络加深,一般信道都会增加)。

 

Inception网络

 

如图一个输入层,inception层的作用是代替人工来确定卷积层中过滤器的类型,或者确定是否需要创建卷积层或池化层。

方法就是你可以将所有可能的过滤器或池化层都用一遍,然后将可能的结果叠加起来,让网络自己来学习需要使用到哪个过滤器或哪些过滤器的组合。使用这个方法你需要注意各种输出需要一样的长和宽(这里我没搞清楚各个过滤器如何做到都输出28x28的,他也没说用padding)。

 

当我们把上面inception层中5x5过滤器计算的那一块输出(图中紫色)单独拿出来看,要计算这一块就需要1.2亿次运算。注意,这个120M的结果是用输出层倒推的, 28x28x32个输出数据,每个数据又是用5X5X192的过滤器算出来的,没有提具体怎么卷积。所以估计还是用padding吧

 

为了减少运算代价,在保证输入和输出不变的情况下,中间可以加一个瓶颈层,这一层用1x1的卷积得到(上一节提到过这种卷积有压缩信道数量的作用)。然后再用一个很低信道的输入去计算结果。瓶颈层是网络中最小的部分,我们先缩小网络表示再扩大它。这一次总的计算成本是12.4M.是上一种方法的十分之一(计算中所涉及的加法运算和乘法近似相等,所以只考虑了乘法)。

结尾说到,只要合理构建瓶颈层,就可以不影响网络的性能。(我之前也考虑过,突然缩小网络会不会丢失信息)

 

如图一个输入,然后接一个inception网络,3x3和5x5由于计算代价太大我们在之前加了1x1卷积(因为这两个卷积需要的输入不一样,所以不能用同一个1x1卷积),最下面是池化(这有一个问题,如果输入和输出的长和宽不变那池化还有意义吗?作者确实提到了要使用padding,但是具体作用还没有理解透彻),由于最大池化不改变原网络的信道数量,所以再加入一个1x1卷积压缩信道,这就避免了最后的输出中池化层的输入占了所有的通道。最后再将这些全都连一块。

 

使用开源的实现方案

本视频讲解如何使用Github,并强烈建议从开源的项目开始学习和实现,也强烈建议把自己的工作开源。

 

迁移学习

如果你要做一个计算机视觉的应用,如果你能下载别人已经训练好的网络,那么进展会相当快。例如很多算法都是在常听说的一些数据集上训练优化过的,这意味着你可以直接使用别人花了几周或几个月用了很多个GPU(这是一个十分枯燥的过程)训练出来的结果,用迁移学习迁移到你自己的问题上。

 

假设你自己有两只猫,你需要训练一个识别是A或者B或者二者都不是的分类器,但你现在又没有很多这两只猫的图片,那么就可以在网上下载一些神经网络(把代码和权重都下载下来)。这个时候你把原先网络的最后的softmax层替换为你自己的三元分类层(原网络可能有成百上千个情况的分类),然后将前面的网络看作是冻结的,只训练你的softmax层,也能得到比较不错的结果。

如果你有一个更大一些的数据集,就应该冻结更少的层,训练后面的几层。总而言之,你的数据越多,训练的层就应该越多(倒着解封),最极端的情况是,你可以只把原作者的权重作为随机初始化,来完全训练自己的权重。

在计算机视觉领域,除非你有一个非常非常大的数据集,否则迁移学习应该是一个很常用的方法。

 

数据扩充(增强)

计算机视觉领域是数据总是不够用,这里提供一些扩充数据集的方法

 

posted @ 2022-04-09 11:49  诸葛村夫CC  阅读(70)  评论(0编辑  收藏  举报