作者——Zahar Chikishev

人工智能看“手相”?这回不是形而上学而是Fast AI的经典案例!_图像_数据 绘影字幕

利用较小的演习数据集检测图像的关键点位置。

要演习一个可以准确预测手指和手掌线条位置的网络,须要多少张贴有标签的图像?我的灵感来自于这篇博客(https://towardsdatascience.com/fun-with-small-image-data-sets-part-2-54d683ca8c96)。
在这篇博客中,作者谈及,从每次演习的135张图片中区分出某一人是否配带眼镜的准确率高达97.5%。
那么回到正文,从15个不同人的60幅贴有标签的图像中,我的任务能得到什么样的准确性?

12个检测点

其目的是准确估计一个手部图像12个点的x和y坐标。
4个点在指尖,4个点在指根,其余4个点沿着掌心线等距,第一个点和末了一个点恰好在这条线的出发点和终点。

这些演习所需的照片是我朋友的照片。
每人6张,左手3张,右手3张。
这些照片是用不同的智好手机在不同白色背景和不同灯光条件下拍摄的。
60张图片都是我手工标注的。

对付神经网络的处理,我利用基于PyTorch的fastai library v1.0.42(https://www.fast.ai/2018/10/02/fastai-ai/)。
作为IDE的Jupyter条记本,和我条记本的NVidia GTX 960M 4Gb VRAM进行演习。
我所得结果的总演习韶光是25小时,考虑到这个GPU远远不是目前市场上最好的硬件,以是25个小时也还不错。

这个项目的主题是数据扩充,幸运的是Fast AI供应了高效的图像转换算法,并供应了干净的API来定义它们。
让我们深入谈论细节。

数据和模型

将标记后的数据分为51幅演习图像和9幅验证图像。
验证图像包括3张人的照片,以及6张既不涌如今演习集上也不与演习中上的任何人共用背景或相机的照片。
所有右手的图像在预处理中我们都进行了水平翻转(如下图所示)。

所有进行过标记的演习图片

在如此小的数据集上进行数据增强是必要的,我对进着迷经网络的每个图像采纳了随机缩放、旋转、亮度和比拟度转换等等。
Fast AI库许可我们随意马虎地定义它。
在底层,同样的仿射变换也运用于标签点。
图像按照样本均值和序列集的方差进行归一化,个中每个RGB通道单独进行归一化,并按4:3的比例调度大小,更详细地说,是384×288像素。
听起来有很多东西须要我们定义。
但令人惊异的是,全体数据定义可以归结为以下代码片段:

这个模型是标准的resnet34。
从resnet34中删除末了两个分类层,然后加上1x1卷积来减少通道数,并与两个完备连接的层相连。
第二个全连通层输出24个激活,经由双曲正切激活函数后表示为12个关键点的x、y坐标。

但有时用代码说话更好:

代码头部的定义利用了常规的PyTorch语法和模块,除了我写的重塑模块之外,它还重构了张量。
这个重塑是必要的,由于我的标签坐标在内部由Fast AI表示为12×2张量,它须要匹配。
其余,标签被Fast AI重定位到[-1;1]范围,以是这里利用双曲正切激活函数比较得当。

优化目标是使演习中的L1丢失最小化。

有两个额外的准确性指标来判断网络的性能和进度。
第一个和第二个指标分别为0.1和0.01。
即,在验证集上打算实际标签与预测坐标偏差在0.1和0.01之间的比例。
这里标签的范围也是[-1;1],给定图像大小为384×288像素。
我们可以很随意马虎地皮算出第二个度量许可高度和宽度的最大偏差分别为1.92和1.44像素。

神经网络演习

神经网络演习是通过运行这行代码40次来完成的:

除了利用Adam optimizer定期进行100个迭代次数的演习外,Fast AI方法还具较好的学习率和动量策略,这是Fast AI在广泛的运用中利用的一种更快收敛的方法。
更多细节见Sylvain Gugger的博客(https://sgugger.github.io/the-1cycle-policy.html)。
我创造它很适宜我的模型。
对付每100个演习周期而言,在50个演习周期之后,缺点率比开始时要高,但是在周期结束时,缺点总是会得到改进。
如果你还是不明白,请看下面这张图片。

学习速率(左)和动量(右)在100个epoch变革。

迭代次数丢失为2500到2600,每回迭代次数有8批。
我们在迭代次数 2500中添加了更多的数据。

这个学习速率和动量的过程称为1cycle策略。
听说,它还有助于对抗过度拟合,而且它彷佛比我考试测验过的其他选项收敛得更快。

我将演习分为5个步骤,以帮助大家理解不同变革的影响:

1500个迭代次数, resnet34个骨干层\"大众冻结\"大众在ImageNet的预演习值上,只演习自定义头层,并且仅利用35个演习图像集。
300个迭代次数后,\"大众解冻\"大众骨干层。
700个迭代次数后,增加了更多的数据扩充。
详细来说,max_zoom 5%到10%,max_warp 5%到20%,max_rotate 5到10度。
500个迭代次数后,从其余4个人那里向演习集添加了16个图像。
使演习集的总大小达到51。
1000个迭代次数后,每个cycle减少20%的学习率,末了一个cycle达到1e-5旁边的学习率。
记住,每个周期是100个迭代次数。

以下图表总结了进展情形:

在4000个迭代次数后的演习中丢失和准确性度量。

这5个步骤中的每一个都对模型进行了额外的改进。
数据扩充中的转换尤其主要,它对验证集缺点的改进有主要贡献。
\"大众解冻\"大众和更多的数据也为验证集供应了很好的改进。
另一方面,虽然降落学习率显著改进了演习集的缺点,但并没有较大的打破。
过度拟合在这里是一个真正的问题,利用较小的学习率会使情形变得更糟。

总的来说,在演习过程中,网络共看到14.7万张不同的变换图像,演习韶光为25.5时。

谈论的结果

演习集的终极均匀L1偏差为0.46像素,而验证集的均匀L1偏差为1.90像素。
此外,演习集的这个分数是针对转换后的图像,而验证图像则没有转换。
这是明显的过拟合。

只管如此,结果还是相称不错的,验证集推断如下图所示。
把稳,绿色的点是实际的标签,赤色的点是终极模型的预测。
从结果上看,该模型彷佛使其预测更具有全局性和相互依赖性,而不是给局部边缘更多的权重。

终极结果:图1、图2和图3是演习集中不同人的手。
图4到6和图7到9是没有涌如今演习凑集中两个人的手。
绿色的点是实际的标签,赤色的点是预测的结果。

模型改进的明确方向是更多的数据和更智能的数据扩充。
均匀偏差仍旧须要小4-5倍才可以。

是哪里涌现了问题?

在不同的地方添加dropout层等是没有用的。
这可能是由于利用1cycle策略的高学习率本身便是一种正则化的形式,不须要更多的正则化。
为不同的层组选择不同的学习率也是一个去世胡同。

如果一开始就删除BatchNorm层,模型就会停滞演习,纵然学习率更低(1e-5)。

我考试测验了其余两种骨干模型架构,Darknet(https://docs.fast.ai/vision.models.html)和U-Net(https://docs.fast.ai/vision.models.unet.html#vision.models.unet),它们具有不同的自定义头部,但是在我的实验中,它不如大略的resnet34事情得好。

末了,Fast AI库在这一点上只有仿射变换(平行线映射到平行线)和透视变换(直线映射到直线)。
考虑到数据增强在这个项目中的主要性,我进行了一个额外的转换,如图所示。
然而,由于某些缘故原由,它并没有带来改进。

结论

该模型仅用51幅演习图像就达到了较好的预测精度。
越来越多的数据被证明可以提高精度,并在一定程度上成功地对抗过度拟合。

Fast AI库是这个项目的一个得当工具,它有以下优胜性:

简洁但灵巧的数据和模型定义用于数据扩充的一系列内置仿射和透视图转换,它们可以自动转换标签点智能学习率和动量策略彷佛能更快地收敛并减少过拟合