前言
本专栏为《人工智能技术学习笔记》。希望以学习笔记的形式和大家一起一步步由浅入深地探索人工智能技术。
本篇为第二篇,带你了解机器视觉处理和其中的图像分类问题。
目录
二、图像分类问题
2.1 尝试使用全连接神经网络
2.2 引入卷积神经网络
2.3 分类函数Softmax
2.4 交叉熵损失函数
2.5 学习率优化算法
2.6 图像预处理算法
2.6.1 随机改变亮暗、对比度和颜色等
2.6.2 随机填充
2.6.3 随机裁剪
2.6.4 随机缩放
2.6.5 随机翻转
2.6.6 随机打乱真实框排列顺序
机器视觉(Machine Vision),是一门让机器学会如何去“看”的学科,是深度学习技术的一个重要应用领域,被广泛应用到安防、工业质检和自动驾驶等场景。
目前主流的计算机视觉任务,主要包括图像分类、目标检测、图像分割、OCR、视频和图像生成等。
图像分类利用计算机对图像进行定量,把图像或图像中的像元或区域划分为若干个类别中的某一种,如图所示:
图像分类是计算机视觉中重要的基本问题,也是图像检测、图像分割、物体跟踪、行为等其他高层视觉任务的基础。
本篇通过手写数字识别这个典型的图像分类任务(0~9个数字一共是10个类别),来了解图像分类问题的特点,原理和方法。
数字识别是计算机从纸质文档、照片或其他来源接收、理解并识别可读的数字的能力,目前比较受关注的是手写数字识别。手写数字识别是一个典型的图像分类问题,已经被广泛应用于汇款单识别、手写邮政编码识别等领域,大大缩短了业务处理时间,提升了工作效率和质量。
在处理如图所示的手写邮政编码的简单图像分类任务时,可以使用基于MNIST数据集的手写数字识别模型。MNIST是深度学习领域标准、易用的成熟数据集,包含50 000条训练样本和10 000条测试样本。
任务输入:一系列手写数字图片,其中每张图片都是28×28的像素矩阵。任务输出:经过了大小归一化和居中处理,输出对应的0~9的数字标签。
我们首先尝试使用典型的全连接神经网络,再引入适合图像处理任务的卷积神经网络。
经典的全连接神经网络来包含四层网络:输入层、两个隐含层和输出层,将手写数字识别任务通过全连接神经网络表示:
输入层:将数据输入给神经网络。在该任务中,输入层的尺度为28×28的像素值。隐含层:增加网络深度和复杂度,隐含层的节点数是可以调整的,节点数越多,神经网络表示能力越强,参数量也会增加。在该任务中,中间的两个隐含层为10×10的结构,通常隐含层会比输入层的尺寸小,以便对关键信息做抽象,激活函数使用常见的Sigmoid函数。输出层:输出网络计算结果,输出层的节点数是固定的。如果是回归问题,节点数量为需要回归的数字数量。如果是分类问题,则是分类标签的数量。在该任务中,模型的输出是回归一个数字,输出层的尺寸为1。
Python源码 – 激活函数为sigmoid的多层网络参考代码:
损失函数收敛曲线如下
显然,全连接神经网络模型并不适合处理图像,因为它会丢失图像像素之间的信息。图像分类任务需要考虑图像数据的空间性,以及如何分类(波士顿价预测是回归任务,是回归到一个具体数字,手写数字识别实际上是进行分类判断),对于图像识别和分类任务,我们需要引入卷积神经网络,Softmax激活函数以及交叉熵损失函数,整个流程如下图:
图像识别需要考虑数据的空间分布,更适合使用卷积神经网络模型,模型中包含卷积层(convolution)和池化层(subsampling),以及最后一个全连接层(fully connected)
卷积神经网络由多个卷积层和池化层组成,如图所示。卷积层负责对输入进行扫描以生成更抽象的特征表示,池化层对这些特征表示进行过滤,保留最关键的特征信息。
关于卷积神经网络,可以参考这一篇:
PyTorch学习系列教程:卷积神经网络【CNN】 – 知乎
关于卷积核和输入,输出通道,可以参考这一篇:
如何理解卷积神经网络中的通道(channel)_卷积通道数_叹久01的博客-CSDN博客
Python源码 – 卷积神经网络实现代码(基于百度飞桨):
运行后损失函数变化曲线如下,从损失函数变化趋势看,全连接神经网络和卷积神经网络收敛速度相当。目前我们的卷积神经网络做的是一个回归任务,接下来我们尝试将回归任务替换成分类任务。
对于分类问题,真实结果是分类标签,而模型输出是实数值,导致以两者相减作为损失不具备物理含义。
那么,什么是分类任务的合理输出呢?分类任务本质上是“某种特征组合下的分类概率”。
为了进行分类判别,我们需要引入Softmax函数到输出层,使得输出层的输出为不同类别概率的,并且所有概率之和为1,比如[0.1, 0.2, 0.7]
比如,一个三个标签的分类模型(三分类)使用的Softmax输出层,从中可见原始输出的三个数字3、1、-3,经过Softmax层后转变成加和为1的三个概率值0.88、0.12、0。
不同的深度学习任务需要有各自适宜的损失函数。我们以价预测和手写数字识别两个任务为例,详细剖析其中的缘由有如下3点:
(1)价预测是回归任务,而手写数字识别是分类任务,使用均方误差作为分类任务的损失函数存在逻辑和效果上的缺欠。
(2)价可以是大于0的任何浮点数,而手写数字识别的输出只可能是0~9之间的10个整数,相当于一种标签。
(3)在价预测的案例中,由于价本身是一个连续的实数值,因此以模型输出的数值和真实价差距作为损失函数是符合道理的。但对于分类问题,真实结果是分类标签,而模型输出是实数值,导致以两者相减作为损失不具备物理含义。
在模型输出为分类标签的概率时,直接以标签和概率做比较也不够合理,人们更习惯使用交叉熵误差作为分类问题的损失衡量。交叉熵损失函数的设计是基于最大似然思想:最大概率得到观察结果的假设是真的。
正确解标签对应的输出越大,交叉熵的值越接近0;当输出为1时,交叉熵误差为0。反之,如果正确解标签对应的输出越小,则交叉熵的值越大。
要想搞清楚交叉熵,推荐大家读一下这篇文章:损失函数:交叉熵详解 – 知乎
里面又牵涉到极大似然估计理论,推荐阅读这篇文章:极大似然估计思想的最简单解释_class_brick的博客-CSDN博客
在深度学习神经网络模型中,通常使用标准的随机梯度下降算法更新参数,学习率代表参数更新幅度的大小,即步长。当学习率最优时,模型的有效容量最大,最终能达到的效果最好。学习率和深度学习任务类型有关,合适的学习率往往需要大量的实验和调参经验。探索学习率最优值时需要注意如下两点:
学习率不是越小越好。学习率越小,损失函数的变化速度越慢,意味着我们需要花费更长的时间进行收敛,如 图2 左图所示。学习率不是越大越好。只根据总样本集中的一个批次计算梯度,抽样误差会导致计算出的梯度不是全局最优的方向,且存在波动。在接近最优解时,过大的学习率会导致参数在最优解附近震荡,损失难以收敛,如 图2 右图所示。
学习率是优化器的一个参数,调整学习率看似是一件非常麻烦的事情,需要不断的调整步长,观察训练时间和Loss的变化。经过研究员的不断的实验,当前已经形成了四种比较成熟的优化算法:SGD、Momentum、AdaGrad和Adam,效果如图所示。
SGD: 随机梯度下降算法,每次训练少量数据,抽样偏差导致的参数收敛过程中震荡。Momentum: 引入物理“动量”的概念,累积速度,减少震荡,使参数更新的方向更稳定。AdaGrad: 根据不同参数距离最优解的远近,动态调整学习率。学习率逐渐下降,依据各参数变化大小调整学习率。Adam: 由于动量和自适应学习率两个优化思路是正交的,因此可以将两个思路结合起来,这就是当前广泛应用的算法。
在计算机视觉中,通常会对图像做一些随机的变化,产生相似但又不完全相同的样本。主要作用是扩大训练数据集,抑制过拟合,提升模型的泛化能力,常用的方法主要有以下几种:
随机改变亮暗、对比度和颜色随机填充随机裁剪随机缩放随机翻转随机打乱真实框排列顺序
下面是分别使用numpy 实现这些数据增强方法。
2.6.1 随机改变亮暗、对比度和颜色等
2.6.2 随机填充
2.6.3 随机裁剪
随机裁剪之前需要先定义两个函数,和这两个函数将被保存在box_utils.py文件中。
2.6.4 随机缩放
2.6.5 随机翻转
2.6.6 随机打乱真实框排列顺序
——————————————————————————————————————
关注微信公众【数字众生】即刻获取干货满满的 “AI学习大礼包” 和 “AI副业变现指南”