Bootstrap

昇思25天学习打卡营第13天|ResNet50图像分类

1. 学习内容复盘

图像分类是最基础的计算机视觉应用,属于有监督学习类别,如给定一张图像(猫、狗、飞机、汽车等等),判断图像所属的类别。本章将介绍使用ResNet50网络对CIFAR-10数据集进行分类。

ResNet网络介绍

ResNet50网络是2015年由微软实验室的何恺明提出,获得ILSVRC2015图像分类竞赛第一名。在ResNet网络提出之前,传统的卷积神经网络都是将一系列的卷积层和池化层堆叠得到的,但当网络堆叠到一定深度时,就会出现退化问题。下图是在CIFAR-10数据集上使用56层网络与20层网络训练误差和测试误差图,由图中数据可以看出,56层网络比20层网络训练误差和测试误差更大,随着网络的加深,其误差并没有如预想的一样减小。

ResNet网络提出了残差网络结构(Residual Network)来减轻退化问题,使用ResNet网络可以实现搭建较深的网络结构(突破1000层)。论文中使用ResNet网络在CIFAR-10数据集上的训练误差与测试误差图如下图所示,图中虚线表示训练误差,实线表示测试误差。由图中数据可以看出,ResNet网络层数越深,其训练误差和测试误差越小。

了解ResNet网络更多详细内容,参见ResNet论文

数据集准备与加载

CIFAR-10数据集共有6000032*32的彩色图像,分为10个类别,每类有6000张图,数据集一共有50000张训练图片和10000张评估图片。首先,如下示例使用download接口下载并解压,目前仅支持解析二进制版本的CIFAR-10文件(CIFAR-10 binary version)。

构建网络

残差网络结构(Residual Network)ResNet网络的主要亮点,ResNet使用残差网络结构后可有效地减轻退化问题,实现更深的网络结构设计,提高网络的训练精度。本节首先讲述如何构建残差网络结构,然后通过堆叠残差网络来构建ResNet50网络。

构建残差网络结构

残差网络结构图如下图所示,残差网络由两个分支构成:一个主分支,一个shortcuts(图中弧线表示)。主分支通过堆叠一系列的卷积操作得到,shotcuts从输入直接到输出,主分支输出的特征矩阵F(x)加上shortcuts输出的特征矩阵x得到F(x)+x,通过Relu激活函数后即为残差网络最后的输出。

残差网络结构主要由两种,一种是Building Block,适用于较浅的ResNet网络,如ResNet18ResNet34;另一种是Bottleneck,适用于层数较深的ResNet网络,如ResNet50ResNet101ResNet152

Building Block

Building Block结构图如下图所示,主分支有两层卷积网络结构:

  • 主分支第一层网络以输入channel64为例,首先通过一个3×33×3的卷积层,然后通过Batch Normalization层,最后通过Relu激活函数层,输出channel64
  • 主分支第二层网络的输入channel64,首先通过一个3×33×3的卷积层,然后通过Batch Normalization层,输出channel64

最后将主分支输出的特征矩阵与shortcuts输出的特征矩阵相加,通过Relu激活函数即为Building Block最后的输出。

主分支与shortcuts输出的特征矩阵相加时,需要保证主分支与shortcuts输出的特征矩阵shape相同。如果主分支与shortcuts输出的特征矩阵shape不相同,如输出channel是输入channel的一倍时,shortcuts上需要使用数量与输出channel相等,大小为1×11×1的卷积核进行卷积操作;若输出的图像较输入图像缩小一倍,则要设置shortcuts中卷积操作中的stride2,主分支第一层卷积操作的stride也需设置为2

Bottleneck

Bottleneck结构图如下图所示,在输入相同的情况下Bottleneck结构相对Building Block结构的参数数量更少,更适合层数较深的网络,ResNet50使用的残差结构就是Bottleneck。该结构的主分支有三层卷积结构,分别为1×11×1的卷积层、3×33×3卷积层和1×11×1的卷积层,其中1×11×1的卷积层分别起降维和升维的作用。

  • 主分支第一层网络以输入channel256为例,首先通过数量为64,大小为1×11×1的卷积核进行降维,然后通过Batch Normalization层,最后通过Relu激活函数层,其输出channel64
  • 主分支第二层网络通过数量为64,大小为3×33×3的卷积核提取特征,然后通过Batch Normalization层,最后通过Relu激活函数层,其输出channel64
  • 主分支第三层通过数量为256,大小1×11×1的卷积核进行升维,然后通过Batch Normalization层,其输出channel256

最后将主分支输出的特征矩阵与shortcuts输出的特征矩阵相加,通过Relu激活函数即为Bottleneck最后的输出。

主分支与shortcuts输出的特征矩阵相加时,需要保证主分支与shortcuts输出的特征矩阵shape相同。如果主分支与shortcuts输出的特征矩阵shape不相同,如输出channel是输入channel的一倍时,shortcuts上需要使用数量与输出channel相等,大小为1×11×1的卷积核进行卷积操作;若输出的图像较输入图像缩小一倍,则要设置shortcuts中卷积操作中的stride2,主分支第二层卷积操作的stride也需设置为2

构建ResNet50网络

ResNet网络层结构如下图所示,以输入彩色图像224×224224×224为例,首先通过数量64,卷积核大小为7×77×7stride2的卷积层conv1,该层输出图片大小为112×112112×112,输出channel64;然后通过一个3×33×3的最大下采样池化层,该层输出图片大小为56×5656×56,输出channel64;再堆叠4个残差网络块(conv2_xconv3_xconv4_xconv5_x),此时输出图片大小为7×77×7,输出channel2048;最后通过一个平均池化层、全连接层和softmax,得到分类概率。

对于每个残差网络块,以ResNet50网络中的conv2_x为例,其由3Bottleneck结构堆叠而成,每个Bottleneck输入的channel64,输出channel256

如下示例定义make_layer实现残差块的构建,其参数如下所示:

  • last_out_channel:上一个残差网络输出的通道数。
  • block:残差网络的类别,分别为ResidualBlockBaseResidualBlock
  • channel:残差网络输入的通道数。
  • block_nums:残差网络块堆叠的个数。
  • stride:卷积移动的步幅。

ResNet50网络共有5个卷积结构,一个平均池化层,一个全连接层,以CIFAR-10数据集为例:

  • conv1:输入图片大小为32×3232×32,输入channel3。首先经过一个卷积核数量为64,卷积核大小为7×77×7stride2的卷积层;然后通过一个Batch Normalization层;最后通过Reul激活函数。该层输出feature map大小为16×1616×16,输出channel64
  • conv2_x:输入feature map大小为16×1616×16,输入channel64。首先经过一个卷积核大小为3×33×3stride2的最大下采样池化操作;然后堆叠3[1×1643×3641×1256][1×1643×3641×1256]结构的Bottleneck。该层输出feature map大小为8×88×8,输出channel256
  • conv3_x:输入feature map大小为8×88×8,输入channel256。该层堆叠4[1×11283×31281×1512]结构的Bottleneck。该层输出feature map大小为4×44×4,输出channel512
  • conv4_x:输入feature map大小为4×44×4,输入channel512。该层堆叠6[1×12563×32561×11024]结构的Bottleneck。该层输出feature map大小为2×22×2,输出channel1024
  • conv5_x:输入feature map大小为2×22×2,输入channel1024。该层堆叠3[1×15123×35121×12048]结构的Bottleneck。该层输出feature map大小为1×11×1,输出channel2048
  • average pool & fc:输入channel2048,输出channel为分类的类别数。

如下示例代码实现ResNet50模型的构建,通过用调函数resnet50即可构建ResNet50模型,函数resnet50参数如下:

  • num_classes:分类的类别数,默认类别数为1000
  • pretrained:下载对应的训练模型,并加载预训练模型中的参数到网络中。

模型训练与评估

本节使用ResNet50预训练模型进行微调。调用resnet50构造ResNet50模型,并设置pretrained参数为True,将会自动下载ResNet50预训练模型,并加载预训练模型中的参数到网络中。然后定义优化器和损失函数,逐个epoch打印训练的损失值和评估精度,并保存评估精度最高的ckpt文件(resnet50-best.ckpt)到当前路径的./BestCheckPoint下。

由于预训练模型全连接层(fc)的输出大小(对应参数num_classes)为1000 为了成功加载预训练权重,我们将模型的全连接输出大小设置为默认的1000CIFAR10数据集共有10个分类,在使用该数据集进行训练时,需要将加载好预训练权重的模型全连接层输出大小重置为10

此处我们展示了5epochs的训练过程,如果想要达到理想的训练效果,建议训练80epochs

可视化模型预测

定义visualize_model函数,使用上述验证精度最高的模型对CIFAR-10测试数据集进行预测,并将预测结果可视化。若预测字体颜色为蓝色表示为预测正确,预测字体颜色为红色则表示预测错误。

由上面的结果可知,5epochs下模型在验证数据集的预测准确率在70%左右,即一般情况下,6张图片中会有2张预测失败。如果想要达到理想的训练效果,建议训练80epochs

2.平台实验结果

;