前言
提起卷积神经网络(CNN),应该很多人都有所耳闻。自从2012年AlexNet在ImageNet挑战赛一举夺魁,它再一次的回到的人们的视野。
为什么称之为"再一次",因为CNN并不是近几年的产物,早在20世纪90年代Yann LeCun就提出了最基础的卷积神经网络模型(LeNet),但是由于算力和数据的限制,它一直处于一种被冷遇的地位,传统目标识别方法,例如之前所讲到的SIFT、HOG、DPM占据着不可撼动的统治地位。
但是随着算力的提升和数据集的积累,这一切都变了,在AlexNet成功之后,CNN如同雨后春笋一样,每年各种各样的Net数不胜数,近其中知名的就有AlexNet、VGG、GoogleNet、UNet、R-CNN、FCN、SSD、YOLO等。
入门计算机视觉领域的绝大多数同学应该都学过或听说过斯坦福大学的公开课(CS231n: Convolutional Neural Networks for Visual Recognition),主要就围绕CNN进行展开,甚至很多近几年入门计算机视觉的同学就斩钉截铁的认为,计算机视觉就是卷积神经网络,我认为这有一些"一叶障目,不见泰山的"感觉。
CNN只是计算机视觉的一个子集,而且是一个很小的子集,更确切的说,计算机视觉是一种应用性技术,CNN是一种工具。
但是,不可否认,CNN是目前阶段我们能力所达到的、在大多数CV方向应用最为成功的一项技术,尤其是R-CNN系列和YOLO系列,在商业中,例如交通监测、车站安检、人脸识别应用非常多,效果对比于传统目标识别算法也要好很多,所以,它是学习计算机视觉中非常重要的一环,本文就概述一下近年来比较成功的CNN模型。本文只是用简略的语言进行概述,后续会挑选一些比较经典的模型进行详解和编程实现。
卷积神经网络概述
按功能对卷积神经网络进行分类主要可以分为两类,
- 检测(detection)
- 分割(segmentation)
检测的目的是要判断一副图像中是否有特定的目标,以及它所在的位置,通过一些手段识别出它所在的包围合区域。
分割的目的要更加严格一些,它不仅要识别出目标的所在区域,还要分割出目标的边缘,尤其在CNN图像分割领域,和传统的图像分割不同,它不能简单的依靠梯度变化幅度把目标分割出来,还需要进行语义上的分割,识别到像素级的类别。
目前比较知名的用于识别的CNN模型有,
- AlexNet
- VGG
- R-CNN系列
- Resnet
- MobileNet
- YOLO系列
在分割方面比较知名的CNN模型有,
- Mask R-CNN
- FCN
- U-Net
- SegNet
CNN中主要用到的技术
系统学习以上上述所提到的知名CNN模型会发现,其中所使用到的技术手段大同小异,而那些知名度较小的CNN模型更是如此,创新点更是微乎其微,其中所使用到的技术主要有,
- 卷积
- 池化
- 基础块
- Dropout
- 跳跃连接
- 锚点
- 优化算法
- 激活函数
- 批量正则化
- 回归
卷积和池化是非常基础的,在特征提取过程中至关重要。
基础块的思想最初出自于VGG,它在AlexNet的基础上进行了很大的改进,基础块思想的引入增加了网络的重用性,后续很多模型都死在这一举出上进行改进的,因此,在很多后续的网络模型都是以VGG为基础模型。
Dropout这个几乎成了CNN模型中必不可少的一个组件,它在应对过拟合问题中具有非常重要的价值。
跳跃连接最初出现在ResNet,在网络的不断改进中发现,其中的思想都是使网络越来越深,网络适当的加深的确能够带来识别精度的提到,但是真的越深越好吗?当然不是。随着网络的加深,很容易出现梯度消失和梯度爆炸现象,ResNet中提出的跳跃连接在后来的网络模型中扮演者非常重要的角色。
锚点这一概念最初是在2008年的DPM模型中看到,后来Faster R-CNN中主要的使用了这项技术,使得它名声大噪,后来的经典模型几乎都用到了锚点这个思想。
优化算法对于上述CNN模型的价值自然不言而喻,梯度下降、Adam、牛顿法等,可以说这是深度计算机视觉的核心所在,也是理论体系最完善、最能够用数学模型解释的一部分。
激活函数和Dropout一样,也是CNN模型中必不可少的一个组件,它的主要价值在于解决模型的线性不可分问题,把非线性的特性引入到网络模型中。
批量正则化也是CNN中常用的一个功能,它的主要作用是加速模型的收敛,避免深层神经网络的梯度消失和梯度爆炸。
回归中用到的较多的自然是softmax,它将经过各种网络层处理得到的特性向量进行回归,得到每一个类别对应的概率,在多分类问题中是一个必不可少的功能。
CNN模型架构
纵观上述所提及的经典CNN模型,它们的模型架构非常相似,主要包含如下几个部分:
- 输入层
- 特征提取层
- 全连接层
- 回归
- 输出层
输入层主要是用于读取图像,用于后面的网络层使用。
特征提取层主要通过卷积来获取图像局部的特征,得到图像的特征图。
全连接层用于对特征层进行后处理,然后用于回归层处理。
回归主要通过一些回归函数,例如softmax函数来对前面得到的特征向量进行处理,得到每个类别对应的概率。
输出层用于输出检测和分类的结果。
当然,在这个过程中某些环节会用到上述提到的激活函数、批量正则化、优化算法以及非极大值抑制。
搭建CNN目标识别系统
有了上述强大的模型,在实际项目中该怎么搭建一个有价值的CNN目标识别系统呢?我认为主要分为如下几个步骤,
- 数据获取
- 数据预处理
- 模型搭建
- 数据后处理
在CNN,乃至整个深度学习领域都可以说数据获取是至关重要的一部分,甚至可以说占据了超过50%的地位。深度学习的发展主要就是得益于这么多年来数据的积累,很多项目和工程也是由于数据的限制和却是只能中途作废。因此,数据获取部分是搭建目标识别系统中最重要的一个环节,它直接决定着是否能够继续走下去。
目前有一些公开的数据集可以获取,例如MNIST、Pascal VOC、ImageNet、Kaggle等。如果自己所做的方向恰好巧合,这些公开数据集里有相应的数据,那么的确是幸运的,可以从这些数据中直接获取。
数据预处理对于CNN同样非常重要,各种视频、摄像头在数据采集的过程中很难保证数据是有价值的,或者干净的,这里就需要对数据进行去噪、去模糊、增强分辨率,如果数据集不充足,还需要对数据进行扩充。
模型搭建我认为是这几个环节中相对较为容易的一部分,首先目前这些经典的框架都有开源的项目,有的甚至不止一个版本,我们可以借鉴甚至直接拿来用这些模型。即便不愿意选择开源的项目,也可以使用tensorflow、pytorch进行搭建,其中需要的代码量是非常有限的。
输出检测的结果需要进行非极大值抑制、绘出包围合等后续工作,以及和一些系统进行对接,这样它才是一个可用的完整系统。