一篇文章读懂图像识别算法的来龙去脉
图像识别算法是计算机视觉中非常重要且基础的分支,类似于人类对图像内容的识别其主要任务是通过对图像中像素分布及颜色、纹理等特征的统计,将图像内容所属类别进行正确的分类。在深度学习中,图像识别模型在完成本职任务的同时还充当计算机视觉其他任务的特征提取网络(Backbone)。本文将从传统算法到深度学习算法,系统的对图像识别算法进行介绍。
传统算法思路
在介绍深度学习算法之前,我们先看一下图像识别传统算法的思路。王叔叔认为“传统算法更加接近人类对事物理解的认知,了解传统算法可以帮助理解技术的本质”,把深度学习当做黑盒设计的都是耍流氓。
我们思考一下,如何教小孩识别图像中的物体。我们首先会对要区分的目标物体进行归纳总结,以此作为区分类别的关键判据,我们称这类判据为“特征”。比如我们要区分三角形和五角星,那么只需统计“角”的个数再通过拟合机器学习模型(数理统计方法)就可以得到正确的分类了。机器学习模型可以简单理解为是一个高维函数,特征是输入到函数的变量,函数的权重[w1, w2, ..., wn]是通过历史数据利用优化方法求取得全局最优解。当训练好模型后,我们将提取的特征[x1, x2, ..., xn]输入到模型y = w1·x1 + w2·x2 + ... + wn·xn中,便可以得到预测的分类结果y。这里以最简单的线性分类器进行举例,实际情况远比这个例子复杂。
然而,计算机视觉面临的问题远比上面问题复杂,在深度学习爆发之前的很长一段时间里学术界和工业界均在努力的设计更好的“特征”和“分类器”。如描述纹理特征的HOG特征、可以通过kernel解决线性和非线性问题的SVM算法。世界是复杂的,人工经验很难将 恰到好处且准确 的将感性认知转化成数字化的特征进行描述(如经常出现的过拟合和欠拟合问题)。
如果机器学习模型可以通过数据拟合出判别类别的分类器,那可不可以利用数据将可以区分物体本质的特征提取出来呢?按照这个思路,专家学者提出了深度学习算法,从此深度学习一统江湖。
深度学习算法思路
深度学习提出之初主要起到特征提取的作用,2014年左右还经常能看到深度学习+SVM等分类器的两阶段训练模式。这种方式非常直观职责分明,但通过没有额外指导(特定任务的loss)学习到的特征并一定适用于某一具体任务,随着算法的演进,人们逐渐发现利用深度学习端到端的模型能够达到更好的效果。
我们探讨一下为什么深度学习可以提取特征。图像特征的本质是可以高度概括图像内容的抽象画信息,凭借人工经验提取的特征是从人的角度将纹理、颜色、形状等信息从原始像素中提取出来。这些特征都来源于图像的原始像素,虽然是一种高效的信息抽象方式,但同时会损失掉很多信息。既然人工提取的特征来源且基于原始图像计算获取的,为何不利用模型直接在原始数据上学习,这样不就没有信息损失了。然而 图像中包含的有用信息是非常稀疏的,模型过多关注无用信息会导致无法收敛。 卷积神经网络的提出很好的解决了这一问题。
经典卷积神经网络
- 什么是卷积?
卷积是分析数学中的一个概念,通俗易懂的解释卷积就是通过将原始数据与预设权重的卷积核做加权,从原始数据中提取出我们想得到的信息。在图像处理中,经常用不同的卷积核对图像进行处理,如 Laplacian算子 用于提取边缘信息。
上述例子中的卷积核参数,即[0,1,0,1,-4,1,0,1,0]是通过人工经验设置的,它具有较强的可解释性,并且证明了这种设置方式的合理性。如果让算法模型在有标注的数据中自动学习卷积核的参数,那是不是就可以不用人工干预地让算法基于某一特定任务自行提取出有用的特征了?基于这种思想,卷积神经网络横空出世。
- 初代卷积神经网络LeNet
LeNet是由卷积层、池化层、全连接层组成的网络模型。卷积层主要作用是提取图像特征、池化层作用是尽可能保存关键信息的前提下减少计算量、全连接层起到分类器的作用,配合起到非线性变换的激活函数一个CNN的最小系统就组成了。后续研究中虽然有很多CNN的演进和变种,但核心思路和组件都是由上述几部分组成的。
如果将LeNet的中间层结果可视化,可以神奇的发现网络的浅层特征提取的是边缘等low-level特征,深层特征更加抽象,由此佐证了卷积可以提取图像特征、图像识别high-level特征解释性差(人工很难设计)的猜想。
- 几种常见的卷积
常规卷积: 对图像特征进行提取,可通过padding方式补充图像边框,使输出与输入保持一致;
反卷积: 可用于分割模型的decoder阶段,将提取的特征恢复原图像大小;
膨胀卷积: 是扩大卷积感受野的一种方法。
LeNet成功后,理论上卷积核越多就可以提取出更多特征,因此大量研究人员为追求更好的算法效果开始堆叠(加深、加宽)卷积核,但实验并没有达到预期的效果。为提升算法效果,CNN模型衍生出了几大流派。
ResNet流派
理论上卷积层数的增加会带来效果的提升,但实验发现结果并不像想象的样子。当卷积层数增加到一定程度,在训练集的效果反而下降(非过拟合造成,过拟合现象是在训练集上可以达到很高的准确率而在测试集准确率下降)。造成这一问题的原因是在卷积神经网络训练时,会利用链式法则进行反向传播。当卷积层数过多时反向传播的梯度很容易发生消失或爆炸的情况。
ResNet是可以有效解决梯度消失/爆炸的网络结构,由微软亚研提出。相比简单的卷积堆叠,ResNet在每个block中添加了“shortcut connections”。这种方式可以将block输入的梯度直接传递至block输出,从而不论block内的卷积操作是否会导致梯度消失,原始梯度都将被保存并传递下来。shortcut连接通常用identity的方式,即权重为1.如果权重大于1或小于1理论上都会发生梯度爆炸或消失的问题。因为梯度不会消失或爆炸,ResNet的网络层数可以做的很深,常用的有resnet18、resnet50、resnet101,根据算力限制选择就好。
很多学者对ResNet结构进行解读,有一种非常有趣的解释认为 ResNet的“shortcut connections”结构可以想并联电路一样展开,展开后ResNet本质上不是增加了网络的深度而是增加了网络的宽度。 这种解释也不无道理,不管怎么解释在结果为王的时代,只要效果好用就完了!
Inception流派
Inception是另一个重要的流派,由google提出。这个流派有很多版本,基本上每年都有变种和进化。本质思想是利用不同kernel size的卷积核将网络做宽。利用不同size的卷积核可以避免为了增加模型感受野而把网络做的过深的问题。下面是非常经典的inception v1的block结构。
这里不展开讲inception的演进和发展,同样的有很多学者对这种结构的成功进行了解读。有一个比较有意思的观点认为在 inception中1x1的卷积其实起到了resnet中“shortcut connection”的作用 。这种观点不一定完全准确,但可以为我们自己设计网络提供思路。
DenseNet流派
DenseNet可以说是把ResNet的思想发挥到极致的一类网络,它将不同level的feature map进行稠密的连接。这样既最大限度的解决梯度消失/爆炸的问题,又可以将不同level的特征进行融合,从而达到更好地效果。
DenseNet故事性及合理性都很符合直觉,但实际应用并不多。主要原因是 稠密的级联非常耗费显存,并且浅层和深层特征的强连接使量化过程中掉点较为严重。 虽然实际实用较少,但思路还是很有启发性的。
算法落地
通过上面的介绍,应该对图像识别算法思路有了一定了解。现在我们再介绍一下在实际场景中我们需要做哪些工作。
模型选型
选模型就像找对象一样,好用的模型千千万但很难找到适合具体任务的一款。这里分享下大体的思路,成为高手还是需要在工作中进行磨炼。
算力评估: 模型选型前要分析部署的硬件,比如可用算力有多少、是部署在高通等SOC上还是服务器端、业务场景需要达到的帧率是多少。针对上面的分析可以大致确定模型的flops应该在什么范围,再根据flops进行模型筛选。
SOTA模型: 深度学习算法模型并不是黑盒,有很多结构其实是和实际的场景进行绑定设计的。在读paper的时候不仅要搞清楚复杂的数据公式更要多问一个为什么,搞清楚数据公式背后代表的物理意义是什么。比如为什么有encoder-decoder这种结构、transformer为什么效果好、attention解决了什么问题。将这些知识点融会贯通知其然知其所以然,当效果没达到预期的时候才能清楚从何下手。
科学调研: 读paper是算法工程师的日常工作,面对具体任务时怎样从海量的论文中快速挑选出好用的算法是非常重要的技能。一般来讲将范围锁定在CVPR、ICCV、ECCV三大顶会,挑选引用量高的论文。这一阶段可能讲论文范围锁定在十篇左右精读后根据原理将直观合理的论文保留,大概3篇左右。将这三篇在github上搜索,有余力可以全部复现,没有余力可以从star多的论文入手跑出baseline。
通过上面三步,一个初版的模型就产生了。但这个模型离落地仍然很远,需要继续进行下面两个步骤。
效果优化
有了模型baseline后,便知道了模型的下限,接着需要针对初版模型进行效果优化以探模型的效果上限。优化思路有一下几个方面。
数据优化: 针对badcase分析模型在哪些类型的case下效果偏差,也可以利用混淆矩阵等方式对不同类别的bias进行分析,补充效果较弱的类型数据。补充数据一般有三种方式,数据增强、数据补采和模拟数据。利用好数据数据增强可以事半功倍。
模型优化: 另一方面可以对模型层面进行优化,比如增加辅助训练分支迫使模型对我们关注的情况进行学习、增加辅助loss引导模型学习、在输入层进行前处理降低模型学习难度、模型中增加attention、STN等机制等。
其他trick: 除了上述两种方式,还可以利用一些训练trick。比如对batch的优化、对学习率等参数变化逻辑的优化等等。
模型加速
通过效果优化基本得到了模型的上限,那么接下来需要根据芯片算力的实际情况和业务场景的要求对模型进行加速。模型加速大概率会有一定精度损失,因此模型加速和效果是一个tradeoff。模型加速思路如下。
针对模型的: 可以对模型进行剪枝、减少block、利用分组卷积、替换小型backbone、蒸馏等方式。
针对SOC: 可以利用芯片厂商提供的推理框架进行量化,也可以自己开发高性能的推理框架。
总结
本文主要介绍了图像识别算法的设计思路和落地优化思路,希望可以给初学者或者从业者一些启发。由于是思路介绍,很多知识点没有展开阐述,需要读者自行查找资料深入学习。后续在专栏中也会对视觉AI算法的技术点进行分享,希望和大家深入讨论。