在这个故事里,主人公David Brailovsky(就叫阿D吧)参加了一场打算机视觉比赛。
这个寻衅赛哀求基于卷积神经网络(CNN),做出一个识别红绿灯的人工智能运用模型

于是阿D花了10周的韶光,从0开始,一点一滴摸索着,搭建、调试、演习和一个深度学习系统。
而且还在末了的比赛中一举夺魁,赢了5000美元。

主人公把这个有点逆袭的过程,底本来本的写了下来。
量子位也希望对人工智能感兴趣的朋友仔细看一看。
不用担心,并不是AI专家才能理解这篇文章。
由于全文重点在与搭建一个人工智能运用模型的思路和方法,而不是拘泥于技能实现。

从实践运用的角度出发,搭建一个AI模型,并不是从0开始写代码的过程。

一文看懂若何搭建AI应用10周学会深度进修还赢下5千美元

最初,是选择一些功能近似的既有模型,然后进行微调,从而把既有模型的能力,从原来的任务“迁移”到新任务上。
然后利用数据进行演习,演习过程中考试测验不同的调度,以不雅观察哪些调度可以起效,哪些调度没有效果。

这个过程中主要的一步,是把几个较低精度的模型组合在一起,反而得到了较高精度的输出结果。
随后,测试并且得到较好的效果。

如前所述,下文没有过于晦涩的技能内容,量子位选择推举这篇,是由于有助于理解如何在实践中利用人工智能办理问题。

那么,我们就随着阿D的讲述就开始吧。

正文分割线

△一个基于深度学习的交通灯识别分类器Demo左上角是根据图片给出的判断寻衅

我最近在一个交通灯识别寻衅赛中赢得了第一名,这是由一家公司组织的打算机视觉竞赛。
寻衅的目标是识别行车载摄像头拍下的图像中,交通灯的状态。

在任何给定的图像中,要做出这样一个人工智能运用模型(分类器):可以输出场景中是否有交通灯,以及它是赤色还是绿色。
且该当仅识别行驶方向上的交通灯。

上面的三张图像,便是须要预测的三类可能的情形:没有交通灯,赤色或绿色交通灯。

寻衅哀求办理方案基于卷积神经网络,这是一种在利用深度神经网络进行图像识别领域非常盛行的方法。
参赛的算法模型,会被依照准确性以及模型的大小两个维度进行评分。
较小的模型得分更高。
此外,得胜所需的最低准确度为95%。

主理方供应了18659个经由标记的图像作为演习数据。
每个图像都标记为上面提到的三个种别之一。

软件和硬件

我用Caffe深度学习框架(可以理解为一组工具包)来演习模型。
紧张缘故原由是Caffe里有各种各样的预演习模型。

在剖析结果、数据探索和分外脚本的事情中,我利用了Python,NumPy以及Jupyter Notebook。

我还用了亚马逊的GPU实例(g2.2xlarge)用于演习模型。
末了的用度是263美元之巨。
用来演习和运行模型的代码和文件在GitHub上。

终极分类器

终极的分类器在主理方的测试集上,实现了94.955%的精度,模型大小为7.84 MB。
作为比较,GoogLeNet的模型大小为41MB,VGG-16的模型大小528MB。

主理方大发慈悲赞许把94.955%当作95%看待,让我通过最低哀求。

追求更高精度的过程中,伴随大量的试验和缺点。
个中一些我知道背后的逻辑,有些只是“碰尝尝看”。
我将讲述一些在模型中试图改进的事情,有的搞定了有的没搞定。

搞定的部分迁移学习

我从考试测验微调一个模型起步,这是一个在ImageNet图像数据库上用GoogLeNet架构预演习的模型。
很快,这就让我得到> 90%的准确性!

不过,主理方在寻衅的官方页面中提到,通过微调GoogLeNet模型该当可以达到93%的精度。
我也不知道我哪里出了问题。

SqueezeNet

SqueezeNet:具有AlexNet(图像分类模型)级精度,但参数少50倍,模型尺寸小于0.5MB。

由于竞争褒奖利用小模型的办理方案,早期我决定探求一个紧凑的网络模型,尽可能少的参数,仍旧可以产生良好的效果。
但大多数最近发布的网络非常深,有很多参数。

SqueezeNet彷佛是一个非常好的选择,它也有一个在ImageNet上演习好的预演习模型,可用在Caffe的Model Zoo(类似手机上的运用商店)中方便取用。

△SqueezeNet网络架构

网络通过以下办法保持紧凑:

紧张利用1x1卷积过滤,赞助一些3x3

减少3x3过滤的输入通道数

有关更多详细信息,我建议阅读Lab41的博客。

在一些来回调度学习率后,我能够微调预演习模型以及从零开始演习,并且准确度能够达到很好的92%!
很酷!

旋转图像

大多数图像是水平横置的,如上所示,但约2.4%是垂直的,其余还有好多种不同的方向。
如下所示。

虽然这些在数据集中占比不大,但我们仍希望自己的模型也能对他们进行精确分类。

不幸的是,在jpeg图像中没有指定方向的EXIF数据。
起初,我考虑做一些启示式算法来识别天空和相应地翻转图像,但这彷佛没那么大略。

然后我改让图像按照固定角度旋转。
最开始我考试测验演习网络随机以0°,90°,180°,270°进行旋转。
这没什么改进。
但是,当我对每个图像进行四次旋转而得的预测取均匀值时,改进涌现了!

92% → 92.6%。

澄清一下:上面提到的“预测取均匀值”,我的意思是均匀了每个类在4个图像变革中产生的模型的概率。

过采样修剪

在演习期间,SqueezeNet网络默认首先在输入图像上实行随机修剪,我没有对这个进行改动。
这种类型的数据增加使网络更好地泛化。

类似地,当天生预测时,我对输入图像进行了一些修剪以及均匀结果。
我利用5个修剪:4个角和一个中央。
有现成的免费Caffe代码来完成这个任务。

92% → 92.46%

旋转图像与过采样修剪带来了非常轻微的改进。

以较低的学习率进行附加演习

所有模型在一定点后开始过拟合。
我把稳到这点,是看到验证集丢失开始在某一点上升。

40000迭代之后验证集丢失开始上升

我在那个点停滞了演习,由于模型可能不再泛化了。
这意味着学习率没有韶光衰减到零。
我试图规复演习过程,在模型开始过拟合时,把学习率调低10倍。
这大概提高了0-0.5%的精度。

更多的演习数据

起初,我将数据分成3组:演习集(64%),验证集(16%)和测试集(20%)。
几天后,我认为放弃36%的数据可能太多了。
我合并了演习和验证集,并利用测试集来检讨我的结果。

我重新演习了一个模型,加入“图像旋转”和“低速率附加演习”,并得到了如下提升:

92.6% → 93.5%

在演习数据中重新标签缺点

当剖析分类器对验证集的缺点时,我把稳到一些缺点的置信度非常高。
换句话说,模型确定它是一件事(例如绿灯),而演习数据解释是相反的情形(例如红灯)。

把稳,在上面的图中,最右边的栏是相称高的。
这意味着有大量的缺点有着> 95%的置信度。
当仔细检讨这些情形时,我创造这些常日缺点是源自演习集的地面实况(ground-truth),而不是演习好的模型。

我决定在演习集中修复这些缺点。
该当是这些缺点稠浊了模型,使其更难以进行归纳。
纵然终极测试集在地面实况中有缺点,一个更泛化的模型在所有图像中,更有可能达到更高的精度。

我手动标记了709张图像,当时我的一个模型产生了缺点。
这改变了709张图像中337张的地面实况。
这个手工活耗时一小时,我还用了python脚本来提升效率。

以上是重新标记和重新演习模型后的结果。
看起来好多了!

这对模型的提升度为:

93.5% → 94.1%

组合模型

利用几个模型在一起并均匀其结果也提高了精度。
我在演习过程中对参与整体的模型进行了不同类型的修正。
利用从头开始演习的模型(纵然自身准确度较低),结合风雅调教过的预处理模型,我们得到了显著改进的结果。
可能这种办法学习到了更多的特色。

末了我们组合了3个模型,精度为94.1%,94.2%和92.9%,合在一起精度为94.8%。

没搞定的部分

没搞定的太多了!
希望个中的一些想法在别处有用。

与过拟合战斗

当试图处理过度拟合时,我考试测验了几个事情,没有一个产生显著的改进:

增加网络中的丢失率

更多数据增强(随机移位,缩放,倾斜)

分配更多的演习数据:利用90/10分隔而不是80/20

平衡数据集

数据集不是非常平衡:

19%的图像标有没有交通灯

53%的是红灯

28%的是绿灯

我试图利用过采样较不常见的类来平衡数据集,但没有创造任何改进。

区分昼夜

我的直觉是,识别交通灯在白天和夜间是非常不同的。
我想大概我可以帮助这个模型,把它分成两个更大略的问题。

通过不雅观察它们的均匀像素强度,将图像分为白天和黑夜是相称随意马虎的:

你可以看到一个非常自然的图像分离,低均匀值即暗图像,在夜间拍摄,通亮的图像,在白天拍摄。

我试过两种方法,都没有改进结果:

为白天图像和夜间图像演习两个单独的模型

演习网络预测6种分类而不是3种,方法也是预测这天间还是晚上

利用SqueezeNet的更好的变体

我用两个改进的SqueezeNet变体进行了一点考试测验。
第一次利用残留连接和第二次演习与密集→稀疏→密集演习。
没什么用。

交通灯定位

在阅读deepsense.io的一篇关于他们如何赢得鲸鱼识别寻衅的文章后,我试图演习一个定位器,即首先识别交通灯在图像中的位置,然后在一个小区域识别交通灯状态。

我花费数小时用sloth来注释约2000张图片。
当试图演习一个模型,它过拟合得非常快,可能是由于没有足够的标签数据。
大概这个方法可行,如果我能标注更多的图像。

在困难案例上演习分类器

通过挑选分类器置信度小于97%的数据,我跳出30%“难度更高”的图片。
然后我试图只用这些图片演习分类器。
没什么改进。

不同的优化算法

我短暂的利用Caffe的Adam结算期,取代线性降落学习率的SGD,但是没有看到任何改进。

向组合中添加更多模型

由于组合的方法证明有效,我曾考试测验把规模扩大一倍。
我试着改变不同的参数来产生不同的模型,并将它们添加到组合中:初始种子,dropout rate,不同的演习数据(分组方法不同),演习中不同的检讨点。
这些都没有带来显著的改进。

终极分类器细节

我的分类器,末了由三个单独演习的网络组合而成。
它们给每个类的概率,进行加权后的均匀值作为输出。
所有这三个网络都基于SqueezeNet,但各自经由了不同的演习。

一号模型 - 以过采样进行预演习的网络

演习基于重新打标签的演习集(修复地面实况缺点之后)。
这个微调过的模型,基于ImageNet上一个预演习的SqueezeNet模型。

演习期间的数据增强:

随机水平镜像

送入网络之前随机裁剪227×227大小的补丁

测试时,对每个图像进行10各不同的变体预测,然后取打算均匀值作为终极预测。
这10种不同的变体预测是:

5次227×227大小的裁剪:四个角各一次,图片中心一次

对每一个裁剪,都天生一个水平镜像

验证集的模型精度:94.21%

模型大小:~2.6 MB

二号模型 - 增加旋转不变性

和一号模型非常类似,只不过增加的是图像旋转。
在演习韶光期间,图像随机旋转90°,180°,270°或根本不旋转。
在测试时,一号模型中描述的10个变体中的每一个通过旋转90°,180°和270°而产生三个变体。
共有40个变量被我们的模型分类和均匀在一起。

验证集的模型精度:94.1%

模型大小:~2.6 MB

三号模型 - 从头开始演习

这个模型不是微调得来,而是从零开始演习。
即便他的准确性低一些,但是从演习集上学到了不同的特性。
用在一个组合里面时,这可能是有用的。

演习和测试期间的数据增强与一号模型相同:镜像和裁剪。

验证集的模型精度:92.92%

模型大小:~2.6 MB

把模型组合在一起

每个模型输出三个值,表示图像属于三个类中的每一个的概率。
我们用以下权重均匀它们的输出:

一号模型:0.28

二号模型:0.49

三号模型:0.23

我通过对可能的值进行网格搜索并在验证集上测试来找到权重的值。
它们对验证集,可能有点过度拟合,但大概不是太多,由于这是一个非常大略的操作。

验证集的模型精度:94.83%

模型大小:~7.84 MB

在Nexar测试集上的精度:94.955% [撒花]

模型缺点示例

棕榈树上由于眩光产生的绿点,让模型缺点的判断这是一个绿灯旗子暗记。

模型把直行的红灯判断成绿灯。
这种路口不止一个交通灯的情形有点棘手。

图中右侧有一个亮起绿灯的旗子暗记灯,但是模型认为没有交通信号灯。

结语

这是我第一次在一个实际案例中运用深度学习!
效果这么好让我很高兴。
在这个过程中我学到了很多很多。
往后有机会再跟大家互换更多~