2.1经典神经网络
1、LeNet-5
首先看看LeNet-5的网络结构,假设你有一张32×32×1的图片,LeNet-5可以识别图中的手写数字,比如像这样手写数字7。LeNet-5是针对灰度图片训练的,所以图片的大小只有32×32×1。
如果我们从左往右看,随着网络越来越深,图像的高度和宽度在缩小,当时人们并不使用padding,或者总是使用valid卷积,这就是为什么每进行一次卷积,图像的高度和宽度都会缩小,它从最初的32×32缩小到28×28,再到14×14、10×10,最后只有5×5。与此同时,随着网络层次的加深,通道数量一直在增加,从1增加到6个,再到16个。相比现代版本,这里得到的神经网络会小一些,只有约6万个参数。
这个神经网络中还有一种模式至今仍然经常用到,就是一个或多个卷积层后面跟着一个池化层,然后又是若干个卷积层再接一个池化层,然后是全连接层,最后是输出,这种排列方式很常用。经典的LeNet-5网络在池化后进行了非线性函数处理,在这个例子中,池化层之后使用了sigmod函数。
2、AlexNet
AlexNet首先用一张227×227×3的图片作为输入,第一层我们使用96个11×11的过滤器,步幅为4,由于步幅是4,因此尺寸缩小到55×55,缩小了4倍左右。然后用一个3×3的过滤器构建最大池化层,f=3,步幅s为2,卷积层尺寸缩小为27×27×96。接着再执行一个5×5的卷积,padding之后,输出是27×27×276。然后再次进行最大池化,尺寸缩小到13×13。再执行一次same卷积,相同的padding,得到的结果是13×13×384,384个过滤器。再做一次same卷积,就像这样。再做一次同样的操作,最后再进行一次最大池化,尺寸缩小到6×6×256。6×6×256等于9216,将其展开为9216个单元,然后是一些全连接层。最后使用softmax函数输出识别的结果,看它究竟是1000个可能的对象中的哪一个。
实际上,这种神经网络与LeNet有很多相似之处,不过AlexNet要大得多。正如前面讲到的LeNet或LeNet-5大约有6万个参数,而AlexNet包含约6000万个参数。当用于训练图像和数据集时,AlexNet能够处理非常相似的基本构造模块,这些模块往往包含着大量的隐藏单元或数据,这一点AlexNet表现出色。AlexNet比LeNet表现更为出色的另一个原因是它使用了ReLu激活函数。
3、VGG-16
VGG-16网络没有那么多超参数,这是一种只需要专注于构建卷积层的简单网络。VGG-16的这个数字16,就是指在这个网络中包含16个卷积层和全连接层。确实是个很大的网络,总共包含约1.38亿个参数,即便以现在的标准来看都算是非常大的网络。
可以从图中看出,随着网络的加深,图像的高度和宽度都在以一定的规律不断缩小,每次池化后刚好缩小一半,而通道数量在不断增加,而且刚好也是在每组卷积操作后增加一倍。也就是说,图像缩小的比例和通道数增加的比例是有规律的。这种相对一致的网络结构对研究者很有吸引力,而它的主要缺点是需要训练的特征数量非常巨大。
2.2残差网络(ResNet)
1、残差网络的介绍
这节课主要学习跳跃连接(Skip connection),它可以从某一层网络层获取激活,然后迅速反馈给另外一层,甚至是神经网络的更深层。我们可以利用跳跃连接构建能够训练深度网络的ResNets,有时深度能够超过100层。
(1)残差块
ResNets是由残差块(Residual block)构建的,首先我解释一下什么是残差块。
在残差网络中有一点变化,我们将 a [ l ] a^{[l]} a[l]直接向后,拷贝到神经网络的深层,在ReLU非线性激活函数前加上 a [ l ] a^{[l]} a[l],这是一条捷径。 a [ l ] a^{[l]} a[l]的信息直接到达神经网络的深层,不再沿着主路径传递,这就意味着最后这个等式 a [ l + 2 ] = g ( z [ l + 2 ] ) a^{[l+2]}=g(z^{[l+2]}) a[l+2]=g(z[l+2])去掉了,取而代之的是另一个ReLU非线性函数,仍然对 z [ l + 2 ] z^{[l+2]} z[l+2]进行g函数处理,但这次要加上 a [ l ] a^{[l]} a[l],即: a [ l + 2 ] = g ( z [ l + 2 ] + a [ l ] ) a^{[l+2]}=g(z^{[l+2]}+a^{[l]}) a[l+2]=g(z[l+2]+a[l]),也就是加上的这个 a [ l ] a^{[l]} a[l]产生了一个残差块。
在上面这个图中,我们可以画一条捷径,直达第二层。实际上这条捷径是在进行ReLU非线性激活函数之前加上的,而这里的每一个节点都执行了线性函数和ReLU激活函数。所以 a [ l ] a^{[l]} a[l]插入的时机是在线性激活之后,ReLU激活之前。除了捷径,你还会听到另一个术语“跳跃连接”,就是指 a [ l ] a^{[l]} a[l]跳过一层或者好几层,从而将信息传递到神经网络的更深层。
(2)残差网络
如上图所示,把这个普通网络变成ResNet的方法是加上所有跳跃连接,每两层增加一个捷径,构成一个残差块。如图所示,5个残差块连接在一起构成一个残差网络。
如果我们使用标准优化算法训练一个普通网络,比如说梯度下降法,或者其它热门的优化算法。如果没有残差,没有这些捷径或者跳跃连接,凭经验你会发现随着网络深度的加深,训练错误会先减少,然后增多。而理论上,随着网络深度的加深,应该训练得越来越好才对。也就是说,理论上网络深度越深越好。但实际上,如果没有残差网络,对于一个普通网络来说,深度越深意味着用优化算法越难训练。实际上,随着网络深度的加深,训练错误会越来越多。但有了ResNets就不一样了,即使网络再深,训练的表现却不错,比如说训练误差减少,就算是训练深达100层的网络也不例外。
2、残差网络的作用
随着网络深度增加,会出现一种退化问题,也就是当网络变得越来越深的时候,训练的准确率会趋于平缓,但是训练误差会变大,这明显不是过拟合造成的,因为过拟合是指网络的训练误差会不断变小,但是测试误差会变大。为了解决这种退化现象,ResNet被提出。残差网络提高了信息流通,并且也避免了由与网络过深所引起的消失梯度问题和退化问题。
注意一点,如果使用L2正则化或权重衰减,它会压缩 W [ l + 2 ] W^{[l+2]} W[l+2]的值。如果对b应用权重衰减也可达到同样的效果,尽管实际应用中,你有时会对b应用权重衰减,有时不会。这里的W是关键项,如果 W [ l + 2 ] = 0 W^{[l+2]}=0 W[l+2]=0,为方便起见,假设 b [ l + 2 ] = 0 b^{[l+2]}=0 b[l+2]=0,这几项就没有了,因为它们( W [ l + 2 ] a [ l + 1 ] + b [ l + 2 ] W^{[l+2]}a^{[l+1]}+b^{[l+2]} W[l+2]a[l+1]+b[l+2])的值为0。最后 a [ l + 2 ] = g ( a [ l ] ) = a [ l ] a^{[l+2]}=g(a^{[l]})=a^{[l]} a[l+2]=g(a[l])=a[l],因为我们假定使用ReLU激活函数,并且所有激活值都是非负的, g ( a [ l ] ) = 0 g(a^{[l]})=0 g(a[l])=0是应用于非负数的ReLU函数,所以 a [ l + 2 ] = a [ l ] a^{[l+2]}=a^{[l]} a[l+2]=a[l]。这意味着,即使给神经网络增加了这两层,它的效率也并不逊色于更简单的神经网络。
之所以能实现跳跃连接是因为same卷积保留了维度,所以很容易得出这个捷径连接,并输出这两个相同维度的向量。比如输入的维度是128, a [ l + 2 ] a^{[l+2]} a[l+2]的维度是256,再增加一个矩阵,这里标记为 W s Ws Ws, W s Ws Ws是一个256×128维度的矩阵,所以 W s a [ l ] Wsa^{[l]} Wsa[l]的维度是256,这个新增项是256维度的向量。你不需要对 W s Ws Ws做任何操作,它是网络通过学习得到的矩阵或参数,它是一个固定矩阵,padding值为0,用0填充 a [ l ] a^{[l]} a[l],其维度为256,所以者几个表达式都可以。
ResNets实现的GitHub地址https://github.com/KaimingHe/deep-residual-networks
深度学习网络篇——ResNet(论文)
ResNet网络详细解析(转载)
残差resnet网络原理详解(转载)
2.3 1×1 卷积
1、基本流程
这个1×1×32过滤器中的32个数字可以这样理解,一个神经元的输入是32个数字(输入图片中左下角位置32个通道中的数字),即相同高度和宽度上某一切片上的32个数字,这32个数字具有不同通道,乘以32个权重(将过滤器中的32个数理解为权重),然后应用ReLU非线性函数,在这里输出相应的结果。
一般来说,如果过滤器不止一个,而是多个,就好像有多个输入单元,其输入内容为一个切片上所有数字,输出结果是6×6过滤器数量。
所以1×1卷积可以从根本上理解为对这32个不同的位置都应用一个全连接层,全连接层的作用是输入32个数字(过滤器数量标记为 n c [ l + 1 ] nc^{[l+1]} nc[l+1],在这36个单元上重复此过程),输出结果是6×6×#filters(过滤器数量),以便在输入层上实施一个非平凡(non-trivial)计算。这种方法通常称为1×1卷积,有时也被称为Network in Network,在林敏、陈强和杨学成的论文中有详细描述。
2、例子
假设这是一个28×28×192的输入层,你可以使用池化层压缩它的高度和宽度,这个过程我们很清楚。但如果通道数量很大,该如何把它压缩为28×28×32维度的层呢?你可以用32个大小为1×1的过滤器,严格来讲每个过滤器大小都是1×1×192维,因为过滤器中通道数量必须与输入层中通道的数量保持一致。但是你使用了32个过滤器,输出层为28×28×32,这就是压缩通道数( n c nc nc)的方法。
1×1卷积层就是这样实现了一些重要功能的(doing something pretty non-trivial),它给神经网络添加了一个非线性函数,从而减少或保持输入层中的通道数量不变,当然如果你愿意,也可以增加通道数量。
2.4 Inception 网络
1、Inception 网络简介
Inception网络或Inception层的作用就是代替人工来确定卷积层中的过滤器类型,或者确定是否需要创建卷积层或池化层。
有了这样的Inception模块,你就可以输入某个量,因为它累加了所有数字,这里的最终输出为32+32+128+64=256。Inception模块的输入为28×28×192,输出为28×28×256。
基本思想是Inception网络不需要人为决定使用哪个过滤器或者是否需要池化,而是由网络自行确定这些参数,你可以给网络添加这些参数的所有可能值,然后把这些输出连接起来,让网络自己学习它需要什么样的参数,采用哪些过滤器组合。
下图显示了Inception计算成本问题。
如上图第二张图所示,瓶颈层是网络中最小的部分(此处为中间部分),我们先缩小网络表示,然后再扩大它。通过两张图的对比可以明显看到,采用了1*1卷积层的计算成本下降了10倍。
注:1、池化可以改变宽和高。
2、利用1*1卷积层可以改变通道数
2、Inception 网络的扩展
上图为一个Inception模块,形式与第一小节的操作类似,其中最大池化后需要使用32个维度为1×1×192的过滤器,所以输出的维度其通道数缩小为32。这样就避免了最后输出时,池化层占据所有的通道。
最后,将这些方块全都连接起来。在这过程中,把得到的各个层的通道都加起来,最后得到一个28×28×256的输出。通道连接实际就是把所有方块连接在一起的操作。这就是一个Inception模块,而Inception网络所做的就是将这些模块都组合到一起。
其中绿色圆圈中的是在网络的最后几层,通常称为全连接层,在它之后是一个softmax层来做出预测。你应该把它看做Inception网络的一个细节,它确保了即便是隐藏单元和中间层也参与了特征计算,它们也能预测图片的分类。它在Inception网络中,起到一种调整的效果,并且能防止网络发生过拟合。
2.5迁移学习
事实上,网上的公开数据集非常庞大,并且你下载的其他人已经训练好几周的权重,已经从数据中学习了很多了,你会发现,对于很多计算机视觉的应用,如果你下载其他人的开源的权重,并用作你问题的初始化,你会做的更好。
什么是迁移学习(Transfer Learning)?【精讲+代码实例】(转载)
迁移学习概述(Transfer Learning)(转载)
2.6数据增强
1、数据扩充
2、彩色转换
有这样一张图片,然后给R、G和B三个通道上加上不同的失真值。在实践中,R、G和B的值是根据某种概率分布来决定的。这么做的理由是,可能阳光会有一点偏黄,或者是灯光照明有一点偏黄,这些可以轻易的改变图像的颜色,但是对内容的识别,以及标签y,还是保持不变的。所以介绍这些,颜色失真或者是颜色变换方法,这样会使得你的学习算法对照片的颜色更改更具鲁棒性。
其中一种影响颜色失真的算法是PCA,即主成分分析。PCA颜色增强的大概含义是,比如说,如果你的图片呈现紫色,即主要含有红色和蓝色,绿色很少,然后PCA颜色增强算法就会对红色和蓝色增减很多,绿色变化相对少一点,所以使总体的颜色保持一致。
3、利用线程进行数据扩充
左边圆柱为存储训练数据的硬盘。如果你有特别大的训练数据,你可能会使用CPU线程,然后它不停的从硬盘中读取数据,所以你有一个从硬盘过来的图片数据流。你可以用CPU线程来实现这些失真变形,可以是随机裁剪、颜色变化,或者是镜像。从而构成批数据或者最小批数据,这些数据持续的传输给其他线程或者其他的进程,然后开始训练,可以在CPU或者GPU上实现训一个大型网络的训练。
常用的实现数据扩充的方法是使用一个线程或者是多线程,这些可以用来加载数据,实现变形失真,然后传给其他的线程或者其他进程。
2.7计算机视觉现状
下图为机器学习数据范围图谱。你会发现当你有很多数据时,人们倾向于使用更简单的算法和更少的手工工程,因为我们不需要为这个问题精心设计特征。当你有大量的数据时,只要有一个大型的神经网络,甚至一个更简单的架构,可以是一个神经网络,就可以去学习它想学习的东西。
图像识别其实是如何看图片的问题,并且告诉你这张图是不是猫,而对象检测则是看一幅图,你画一个框,告诉你图片里的物体,比如汽车等等。因为获取边框的成本比标记对象的成本更高,所以我们进行对象检测的数据往往比图像识别数据要少。
所以当我看机器学习应用时,我们认为通常我们的学习算法有两种知识来源,一个来源是被标记的数据,就像(x,y)应用在监督学习。第二个知识来源是手工工程,有很多方法去建立一个手工工程系统,它可以是源于精心设计的特征,手工精心设计的网络体系结构或者是系统的其他组件。所以当你没有太多标签数据时,你只需要更多地考虑手工工程。
计算机视觉领域一直以来是出于少数据量的状况下,但近些年有数据增多的趋势,这导致了手工工程的急剧减少,但是手工工程仍不可或缺,这也是为什么计算机视觉的网络非常复杂的原因。
计算机视觉属于小数据系统,因此更好利用开源代码将是一个很多的选择,需要使用开源代码的优势。