卷积
设输入图片大小为n*n,卷积核大小为f*f,周围填充p圈,步长为s,则输出图片大小为
(如果计算结果不是整数,则向下取整)
图像边缘检测
将图片与如下卷积核kernal/过滤器filter进行卷积
1 | 0 | -1 |
1 | 0 | -1 |
1 | 0 | -1 |
也可以用下面的这些卷积核进行卷积:
1 | 0 | -1 |
2 | 0 | -2 |
1 | 0 | -1 |
这种卷积核的优点是增加了中间这一行的权重,这样就可以使得整个系统的鲁棒性(robust a.)更高(鲁棒性指的是计算机软件在输入错误、磁盘故障、网络过载或有意攻击情况下,能否不死机、不崩溃)
如果需要进行水平边缘处理,那直接将整个卷积核顺时针旋转90°即可
当然,最好的办法是直接把卷积核设置成参数,让深度学习自己去算,这样就可以更加灵活地处理不同角度的边缘。
填充padding
填充的原因:
1. 卷积的时候边缘的数据只会被计算一两次,这样就浪费了边缘上的信息,因此需要在图片周围进行一定的填充,这样卷积的时候才能够更多地利用到图片边缘的信息
2. 图片每卷积一次缩小(shrink v.)一圈,这样就会使得图片越来越小,在图片周围进行填充可以让图片进行卷积之后仍然保持原来的大小
需要维持图片原大小的p=(f-1)/2
Valid/Same Convolution
Valid Convolution: p=0
Same Convolution: p=(f-1)/2
卷积核边长一般都是奇数
1. 如果f是偶数那就只能够不对称填充(asymmetric padding n.)输入图片,f是奇数才能够对称填充(natural padding n.)
2. 奇数f可以有一个中心点,这样就可以利用中心点来确定卷积核的位置
3. 其实是大家的习惯(
步长stride
多维卷积
直接把每次对应的27个数字加在一起,最后输出只有一个通道
卷积总结
如果是卷积当中的一层,那么
为卷积核的边长,
为填充宽度,
为步长,
为卷积核数量
输入为(分别表示长、宽、通道数量)
输出为(分别表示长、宽、卷积核数量)
每个卷积核为
激活值=(输出+偏差)*激活函数
(
表示样本数量)
权重weights:
偏差常数bias
卷积神经网络的三种层
卷积层Convolution layer(Conv)
池化层Pooling layer(Pool)
全连接层Fully connected layer(FC)
池化层Pooling Layer
f: 过滤器大小
s: 步长
最大池化/平均池化
输入为,则输出为
Conv1→第一层的卷积层(后面的数字表示第几层)
注意参数尽量使用前人文献里面用过的,可以避免自己试错的时间成本
Why CNN
1. 如果用全连接层来处理的话参数会变得很庞大,而用CNN可以减少参数计算
→CNN为什么能减少参数?
①参数共享parameter sharing:在图像的一部分有用的特征检测器(如垂直边缘检测器)也同样适用于整个图像
②稀疏连接sparsity of connections:每个输出仅和一小部分输入有关
③位移不变性translation invariance:即使平移整个图片几个像素,内容仍然不变
作业:BDBAD/CCBBDC
LeNet-5
用于训练灰度图像,输入32*32*1
(当年使用平均池化较多,现在最大池化更常用)
一般的网络排序方式:Conv→Pool→Conv→Pool→FC→output
过去没有填充,每次处理都会减小图片的大小
过去人们会用Sigmoid(=Logistic)/Tanh,而不会去用ReLu,而且因为过去的运算力不足,所以需要让上一层和这一层的通道数都一样,因此会多出很多放到现在来看不必要的细节
原来的LeNet-5在池化了以后还做了非线性函数处理non-linearity(比如Sigmoid)
AlexNet
→和LeNet-5很像,但是参数多了很多(6000万个参数)
→用了ReLu激活函数
→每个层被拆到不同的GPU上面,然后相互连接,因为当时GPU的处理速度还比较慢
→局部响应归一化层(LRN层)→现在已经不用了
VGG-16
没有很多参数
CONV = 3*3 filter, s=1, same; MAX-POOL = 2*2, s=2
之所以叫VGG-16是因为一共有16个层(包括卷积层和全连接层)
1*1卷积
≈全连接,但是可以改变图片的维度
ResNet残差网络
ResNet→Residual Block
残差好用的原因:
①当权重函数等于0的时候a[l+2]=a[l],这样就可以减少参数计算,提升网络性能
②一般输入输出的通道数一样,大小也一样(same convolution),如果不一样那么就把从前面挪过来的激活层乘上一个空矩阵调整大小
Inception网络
构建卷积层时,要自己决定每一层卷积核的大小,或者要不要添加池化层。而Inception网络的作用就是代替你来决定,虽然网络架构因此变得更加复杂,但网络表现却非常好
输入一张图,然后算法通过计算多个卷积核的同尺寸卷积与池化,然后把这些数据直接堆积在一起
基本思想是Inception网络不需要人为决定使用哪个过滤器或者是否需要池化,而是由网络自行确定这些参数,你可以给网络添加这些参数的所有可能值,然后把这些输出连接起来,让网络自己学习它需要什么样的参数,采用哪些过滤器组合
计算成本
如果我们用普通的卷积方法(如图),计算成本将会是输出数据量×每次卷积计算的总数据量,即(28*28*32)*(5*5*32)=12亿
但是如果我们用1*1卷积,先把图片维度缩小(这个叫做瓶颈期bottleneck)然后再卷积,这样就可以让整体计算量变低
Inception模块就是最好的选择,我们可以应用各种卷积核把输出连接起来,至于计算成本问题,可以通过使用1×1卷积来构建瓶颈层来解决
如何建立一个inception网络
首先建立多个inception模型,将同一块数据用不同的卷积核卷积,最后将输出全都连接在一起形成一个大层,用这个大层代替传统的卷积层与池化层,又因为使用了1*1卷积调整通道数量,所以整体的计算消耗并没有大幅提高
inception是怎么提出的?
作者通过盗梦空间(Inception)里面传出来的一个梗图得到启发,认为深度学习网络还可以做得更深,因此提出了结构更加复杂的Inception网络
迁移学习(Transfer Learning)
下载别人已经训练好网络结构的权重,用这个作为预训练,然后转换到你感兴趣的任务上。
例:建一个猫咪检测器检测自家的两只猫Tigger和Misty
→三分类问题,图片里是Tigger还是Misty,或者都不是
问题:我们自己手上没有足够的图片
解:从网上下载一些神经网络开源的实现(包括代码和权重)比如下图的Imagenet
我们可以去掉原来的softmax,改成我们现在的三个输出(T/M/都不是),这样就不需要我们再自己建立数据集,确定参数训练了
数据增强(Data Augmentation)
计算机视觉的主要问题是没有办法得到充足的数据→数据扩充
①垂直镜像对称
②随机裁剪
③旋转,平移(shearing:此处并非裁剪的含义,图像仅水平或垂直坐标发生变化)图像,可以对图像进行这样的扭曲变形,引入很多形式的局部弯曲等等。当然使用这些方法并没有坏处,尽管在实践中,因为太复杂了所以使用的很少。
④彩色转换
在实践中,R、G和B的值是根据某种概率分布来决定的。这么做的理由是,可能阳光会有一点偏黄,或者是灯光照明有一点偏黄,这些可以轻易的改变图像的颜色,但是对猫的识别,或者是内容的识别,以及标签,还是保持不变的。所以介绍这些,颜色失真或者是颜色变换方法,这样会使得你的学习算法对照片的颜色更改更具鲁棒性。
你可能有存储好的数据,你的训练数据存在硬盘上,然后使用符号,这个圆桶来表示你的硬盘。如果你有一个小的训练数据,你可以做任何事情,这些数据集就够了。
但是你有特别大的训练数据,接下来这些就是人么经常使用的方法。你可能会使用CPU线程,然后它不停的从硬盘中读取数据,所以你有一个从硬盘过来的图片数据流。你可以用CPU线程来实现这些失真变形,可以是随机裁剪、颜色变化,或者是镜像。但是对每张图片得到对应的某一种变形失真形式,看这张图片(编号1),对其进行镜像变换,以及使用颜色失真,这张图最后会颜色变化(编号2),从而得到不同颜色的猫。
与此同时,CPU线程持续加载数据,然后实现任意失真变形,从而构成批数据或者最小批数据,这些数据持续的传输给其他线程或者其他的进程,然后开始训练,可以在CPU或者GPU上实现训一个大型网络的训练。
常用的实现数据扩充的方法是使用一个线程或者是多线程,这些可以用来加载数据,实现变形失真,然后传给其他的线程或者其他进程,来训练这个(编号2)和这个(编号1),可以并行实现。
这就是数据扩充,与训练深度神经网络的其他部分类似,在数据扩充过程中也有一些超参数,比如说颜色变化了多少,以及随机裁剪的时候使用的参数。与计算机视觉其他部分类似,一个好的开始可能是使用别人的开源实现,了解他们如何实现数据扩充。当然如果你想获得更多的不变特性,而其他人的开源实现并没有实现这个,你也可以去调整这些参数。因此,我希望你们可以使用数据扩充使你的计算机视觉应用效果更好。
计算机视觉现状(The state of computer vision)
深度学习已经成功地应用于计算机视觉、自然语言处理、语音识别、在线广告、物流还有其他许多问题。在计算机视觉的现状下,深度学习应用于计算机视觉应用有一些独特之处。在这个视频中,我将和你们分享一些我对深度学习在计算机视觉方面应用的认识,希望能帮助你们更好地理解计算机视觉作品(此处指计算机视觉或者数据竞赛中的模型)以及其中的想法,以及如何自己构建这些计算机视觉系统。
你可以认为大部分机器学习问题是介于少量数据和大量数据范围之间的。举个例子,我认为今天我们有相当数量的语音识别数据,至少相对于这个问题的复杂性而言。虽然现在图像识别或图像分类方面有相当大的数据集,因为图像识别是一个复杂的问题,通过分析像素并识别出它是什么,感觉即使在线数据集非常大,如超过一百万张图片,我们仍然希望我们能有更多的数据。还有一些问题,比如物体检测,我们拥有的数据更少。提醒一下,图像识别其实是如何看图片的问题,并且告诉你这张图是不是猫,而对象检测则是看一幅图,你画一个框,告诉你图片里的物体,比如汽车等等。因为获取边框的成本比标记对象的成本更高,所以我们进行对象检测的数据往往比图像识别数据要少,对象检测是我们下周要讨论的内容。
所以,观察一下机器学习数据范围图谱,你会发现当你有很多数据时,人们倾向于使用更简单的算法和更少的手工工程,因为我们不需要为这个问题精心设计特征。当你有大量的数据时,只要有一个大型的神经网络,甚至一个更简单的架构,可以是一个神经网络,就可以去学习它想学习的东西。
相反当你没有那么多的数据时,那时你会看到人们从事更多的是手工工程,低调点说就是你有很多小技巧可用(整理者注:在机器学习或者深度学习中,一般更崇尚更少的人工处理,而手工工程更多依赖人工处理,注意领会Andrew NG的意思)。但我认为每你没有太多数据时,手工工程实际上是获得良好表现的最佳方式。
所以当我看机器学习应用时,我们认为通常我们的学习算法有两种知识来源,一个来源是被标记的数据,就像,应用在监督学习。第二个知识来源是手工工程,有很多方法去建立一个手工工程系统,它可以是源于精心设计的特征,手工精心设计的网络体系结构或者是系统的其他组件。所以当你没有太多标签数据时,你只需要更多地考虑手工工程。
所以我认为计算机视觉是在试图学习一个非常复杂的功能,我们经常感觉我们没有足够的数据,即使获得了更多数据,我们还是经常觉得还是没有足够的数据来满足需求。这就是为什么计算机视觉,从过去甚至到现在都更多地依赖于手工工程。我认为这也是计算机视觉领域发展相当复杂网络架构地原因,因为在缺乏更多数据的情况下,获得良好表现的方式还是花更多时间进行架构设计,或者说在网络架构设计上浪费(贬义褒用,即需要花费更多时间的意思)更多时间。
幸运的是,当你有少量的数据时,有一件事对你很有帮助,那就是迁移学习。我想说的是,在之前的幻灯片中,Tigger、Misty或者二者都不是的检测问题中,我们有这么少的数据,迁移学习会有很大帮助。这是另一套技术,当你有相对较少的数据时就可以用很多相似的数据。
如果你看一下计算机视觉方面的作品,看看那里的创意,你会发现人们真的是踌躇满志,他们在基准测试中和竞赛中表现出色。对计算机视觉研究者来说,如果你在基准上做得很好了,那就更容易发表论文了,所以有许多人致力于这些基准上,把它做得很好。积极的一面是,它有助于整个社区找出最有效得算法。但是你在论文上也看到,人们所做的事情让你在数据基准上表现出色,但你不会真正部署在一个实际得应用程序用在生产或一个系统上。
(整理着注:Benchmark 基准测试,Benchmark是一个评价方式,在整个计算机领域有着长期的应用。维基百科上解释:“As computer architecture advanced, it became more difficult to compare the performance of various computer systems simply by looking at their specifications.Therefore, tests were developed that allowed comparison of different architectures.”Benchmark在计算机领域应用最成功的就是性能测试,主要测试负载的执行时间、传输速度、吞吐量、资源占用率等。)
下面是一些有助于在基准测试中表现出色的小技巧,这些都是我自己从来没使用过的东西,如果我把一个系统投入生产,那就是为客户服务。
其中一个是集成,这就意味着在你想好了你想要的神经网络之后,可以独立训练几个神经网络,并平均它们的输出。比如说随机初始化三个、五个或者七个神经网络,然后训练所有这些网络,然后平均它们的输出。另外对他们的输出进行平均计算是很重要的,不要平均他们的权重,这是行不通的。看看你的7个神经网络,它们有7个不同的预测,然后平均他们,这可能会让你在基准上提高1%,2%或者更好。这会让你做得更好,也许有时会达到1%或2%,这真的能帮助你赢得比赛。但因为集成意味着要对每张图片进行测试,你可能需要在从3到15个不同的网络中运行一个图像,这是很典型的,因为这3到15个网络可能会让你的运行时间变慢,甚至更多时间,所以技巧之一的集成是人们在基准测试中表现出色和赢得比赛的利器,但我认为这几乎不用于生产服务于客户的,我想除非你有一个巨大的计算预算而且不介意在每个用户图像数据上花费大量的计算。
你在论文中可以看到在测试时,对进准测试有帮助的另一个技巧就是Multi-crop at test time,我的意思是你已经看到了如何进行数据扩充,Multi-crop是一种将数据扩充应用到你的测试图像中的一种形式。
举个例子,让我们看看猫的图片,然后把它复制四遍,包括它的两个镜像版本。有一种叫作10-crop的技术(crop理解为裁剪的意思),它基本上说,假设你取这个中心区域,裁剪,然后通过你的分类器去运行它,然后取左上角区域,运行你的分类器,右上角用绿色表示,左下方用黄色表示,右下方用橙色表示,通过你的分类器来运行它,然后对镜像图像做同样的事情对吧?所以取中心的crop,然后取四个角落的crop。
这是这里(编号1)和这里(编号3)就是中心crop,这里(编号2)和这里(编号4)就是四个角落的crop。如果把这些加起来,就会有10种不同的图像的crop,因此命名为10-crop。所以你要做的就是,通过你的分类器来运行这十张图片,然后对结果进行平均。如果你有足够的计算预算,你可以这么做,也许他们需要10个crops,你可以使用更多,这可能会让你在生产系统中获得更好的性能。如果是生产的话,我的意思还是实际部署用户的系统。但这是另一种技术,它在基准测试上的应用,要比实际生产系统中好得多。
集成的一个大问题是你需要保持所有这些不同的神经网络,这就占用了更多的计算机内存。对于multi-crop,我想你只保留一个网络,所以它不会占用太多的内存,但它仍然会让你的运行时间变慢。
这些是你看到的小技巧,研究论文也可以参考这些,但我个人并不倾向于在构建生产系统时使用这些方法,尽管它们在基准测试和竞赛上做得很好。
由于计算机视觉问题建立在小数据集之上,其他人已经完成了大量的网络架构的手工工程。一个神经网络在某个计算机视觉问题上很有效,但令人惊讶的是它通常也会解决其他计算机视觉问题。
所以,要想建立一个实用的系统,你最好先从其他人的神经网络架构入手。如果可能的话,你可以使用开源的一些应用,因为开放的源码实现可能已经找到了所有繁琐的细节,比如学习率衰减方式或者超参数。
最后,其他人可能已经在几路GPU上花了几个星期的时间来训练一个模型,训练超过一百万张图片,所以通过使用其他人的预先训练得模型,然后在数据集上进行微调,你可以在应用程序上运行得更快。当然如果你有电脑资源并且有意愿,我不会阻止你从头开始训练你自己的网络。事实上,如果你想发明你自己的计算机视觉算法,这可能是你必须要做的。
目标定位(Object localization)
图片分类任务我们已经熟悉了,就是算法遍历图片,判断其中的对象是不是汽车,这就是图片分类。这节课我们要学习构建神经网络的另一个问题,即定位分类问题。这意味着,我们不仅要用算法判断图片中是不是一辆汽车,还要在图片中标记出它的位置,用边框或红色方框把汽车圈起来,这就是定位分类问题。其中“定位”的意思是判断汽车在图片中的具体位置。这周后面几天,我们再讲讲当图片中有多个对象时,应该如何检测它们,并确定出位置。比如,你正在做一个自动驾驶程序,程序不但要检测其它车辆,还要检测其它对象,如行人、摩托车等等,稍后我们再详细讲。
本周我们要研究的分类定位问题,通常只有一个较大的对象位于图片中间位置,我们要对它进行识别和定位。而在对象检测问题中,图片可以含有多个对象,甚至单张图片中会有多个不同分类的对象。因此,图片分类的思路可以帮助学习分类定位,而对象定位的思路又有助于学习对象检测,我们先从分类和定位开始讲起。
图片分类问题你已经并不陌生了,例如,输入一张图片到多层卷积神经网络。这就是卷积神经网络,它会输出一个特征向量,并反馈给softmax单元来预测图片类型。
如果你正在构建汽车自动驾驶系统,那么对象可能包括以下几类:行人、汽车、摩托车和背景,这意味着图片中不含有前三种对象,也就是说图片中没有行人、汽车和摩托车,输出结果会是背景对象,这四个分类就是softmax函数可能输出的结果。
这就是标准的分类过程,如果你还想定位图片中汽车的位置,该怎么做呢?我们可以让神经网络多输出几个单元,输出一个边界框。具体说就是让神经网络再多输出4个数字,标记为,,和,这四个数字是被检测对象的边界框的参数化表示。
我们先来约定本周课程将使用的符号表示,图片左上角的坐标为,右下角标记为。要确定边界框的具体位置,需要指定红色方框的中心点,这个点表示为(,),边界框的高度为,宽度为。因此训练集不仅包含神经网络要预测的对象分类标签,还要包含表示边界框的这四个数字,接着采用监督学习算法,输出一个分类标签,还有四个参数值,从而给出检测对象的边框位置。此例中,的理想值是0.5,因为它表示汽车位于图片水平方向的中间位置;大约是0.7,表示汽车位于距离图片底部的位置;约为0.3,因为红色方框的高度是图片高度的0.3倍;约为0.4,红色方框的宽度是图片宽度的0.4倍。
下面我再具体讲讲如何为监督学习任务定义目标标签 。
请注意,这有四个分类,神经网络输出的是这四个数字和一个分类标签,或分类标签出现的概率。目标标签的定义如下:
它是一个向量,第一个组件表示是否含有对象,如果对象属于前三类(行人、汽车、摩托车),则,如果是背景,则图片中没有要检测的对象,则。我们可以这样理解,它表示被检测对象属于某一分类的概率,背景分类除外。
如果检测到对象,就输出被检测对象的边界框参数、、和。最后,如果存在某个对象,那么,同时输出、和,表示该对象属于1-3类中的哪一类,是行人,汽车还是摩托车。鉴于我们所要处理的问题,我们假设图片中只含有一个对象,所以针对这个分类定位问题,图片最多只会出现其中一个对象。
我们再看几个样本,假如这是一张训练集图片,标记为,即上图的汽车图片。而在当中,第一个元素,因为图中有一辆车,、、和会指明边界框的位置,所以标签训练集需要标签的边界框。图片中是一辆车,所以结果属于分类2,因为定位目标不是行人或摩托车,而是汽车,所以,,,、和中最多只有一个等于1。
这是图片中只有一个检测对象的情况,如果图片中没有检测对象呢?如果训练样本是这样一张图片呢?
这种情况下,,的其它参数将变得毫无意义,这里我全部写成问号,表示“毫无意义”的参数,因为图片中不存在检测对象,所以不用考虑网络输出中边界框的大小,也不用考虑图片中的对象是属于、和中的哪一类。针对给定的被标记的训练样本,不论图片中是否含有定位对象,构建输入图片和分类标签的具体过程都是如此。这些数据最终定义了训练集。
最后,我们介绍一下神经网络的损失函数,其参数为类别和网络输出,如果采用平方误差策略,则,损失值等于每个元素相应差值的平方和。
如果图片中存在定位对象,那么,所以,同样地,如果图片中存在定位对象,,损失值就是不同元素的平方和。
另一种情况是,,也就是,损失值是,因为对于这种情况,我们不用考虑其它元素,只需要关注神经网络输出的准确度。
回顾一下,当时,也就是这种情况(编号1),平方误差策略可以减少这8个元素预测值和实际输出结果之间差值的平方。如果, 矩阵中的后7个元素都不用考虑(编号2),只需要考虑神经网络评估(即)的准确度。
为了让大家了解对象定位的细节,这里我用平方误差简化了描述过程。实际应用中,你可以不对、、和softmax激活函数应用对数损失函数,并输出其中一个元素值,通常做法是对边界框坐标应用平方差或类似方法,对应用逻辑回归函数,甚至采用平方预测误差也是可以的。
以上就是利用神经网络解决对象分类和定位问题的详细过程,结果证明,利用神经网络输出批量实数来识别图片中的对象是个非常有用的算法。下节课,我想和大家分享另一种思路,就是把神经网络输出的实数集作为一个回归任务,这个思想也被应用于计算机视觉的其它领域,也是非常有效的,所以下节课见。