4.3 通过深度学习识别CIFAR-10图像
CIFAR-10数据集包含60 000张32×32像素的3通道彩色图像,并被划分为10个类别,每个类别包含6000张图像。训练集包含50 000张图像,测试集包含10 000张图像。图4-12展示了一些来自上述10个类别的随机实例。
图4-12 CIFAR-10图像示例
我们的目标是识别之前未曾见过的图像,并将其指定为上述10个类别之一。让我们定义一个合适的深度网络。
首先导入一些有用的模块,定义一些常量,然后加载数据集:
网络将学习32个卷积滤波器,每个滤波器的大小为3×3。输出维度与输入形状相同,因此将为32×32,并且用到的激活函数为ReLU函数,这也是引入非线性的一种简单方法。之后,我们进行了最大池化操作,池的大小为2×2,Dropout
为25%:
深度流程的下一个阶段是一个稠密网络,它具有512个单元和ReLU激活,接着是一个随机失活率为50%的随机失活层和一个带有10个类别输出的softmax层,每个类别表示一个分类:
定义完神经网络后,开始训练模型。在本例中,我们拆分数据,并同时计算训练集、测试集和验证集。训练集用于构建模型,验证集用于选择性能最佳的方法,而测试集使用全新且未见过的数据来检验最优模型的性能:
运行代码。该网络经过20次迭代后,达到了66.8%的测试准确度。如图4-13与图4-14所示,我们还打印了准确度和损失变化图,并通过model.summary()
转储(dump)模型。
图4-13 准确度和损失的打印输出
图4-14 定义的深度神经网络的准确度和损失
4.3.1 用更深的网络提高CIFAR-10的性能
一种提高性能的方法是定义具有多个卷积运算的更深的网络。如下例所示,我们有一系列模块:
第一模块:(CONV + CONV + MaxPool + DropOut)
第二模块:(CONV + CONV + MaxPool + DropOut)
第三模块:(CONV + CONV + MaxPool + DropOut)
这些模块之后都是标准的稠密输出层。所有使用的激活函数均为ReLU函数。我们在第1章中也讨论过一个新网络层BatchNormalization()
,它用于为多模块引入一种归一化形式:
恭喜你!你已定义了更深的网络。运行代码,经过40次迭代后达到了82%的准确度!为了完整起见,让我们加上代码的其余部分。第一部分是加载和归一化数据:
因此,相较之前的简单深度网络,获得了15.14%的提升。为了完整起见,我们还打印了训练期间的准确度和损失。
4.3.2 用数据增强提高CIFAR-10的性能
提高性能的另一种方法是为训练提供更多的图像。具体地,可采用标准的CIFAR训练集,再通过多种变换来扩展该集合,比如旋转、尺寸变换、水平或垂直翻转、缩放、通道移位(channel shift)等。让我们看看应用于上节定义的同一网络上的代码:
其中,rotation_range
是随机旋转图片的度数(0~180),width_shift
和height_shift
是垂直或水平随机转换图片的范围,zoom_range
用于随机缩放图片,hori-zontal_flip
用于在水平方向上随机翻转半图,fill_mode
是在旋转或移位后,填充新像素点的策略。
数据增强后,我们从标准CIFAR-10集生成了更多的训练图像,如图4-15所示。
图4-15 图像增强示例
现在,我们可将这种想法直接应用于训练。使用之前定义的相同CNN,我们只需生成更多增强图像,然后进行训练。为了提高效率,图像生成器与模型并行运行。这样能做到在CPU上增强图像的同时,在GPU上并行训练模型。代码如下:
现在,每次迭代都变得更加耗费资源,这是因为我们拥有了更多的训练数据。为此,我们仅运行50次迭代。如图4-16与图4-17所示,这样做后获得了85.91%的准确度。
图4-16 50次迭代结果
图4-17 最终准确度显示为85.91%
图4-18总结了我们实验过程中得到的成果。
图4-18 使用不同网络的CIFAR-10的准确度
可在线获得CIFAR-10的最新技术成果列表(http://rodrigob.github.io/are_we_there_yet/build/classification_datasets_results.html
)。截至2019年4月,最佳成果的准确度为96.53%[3]。
4.3.3 基于CIFAR-10预测
假设我们想用上述训练好的CIFAR-10深度学习模型进行图像的批量评估。
由于保存了模型和权重,因此不需要每次都训练:
现在让我们预测猫和狗。
得到输出类别3(猫)和5(狗),与期望相符。我们成功创建了一个用于CIFAR-10图像分类的CNN。接下来,我们将研究VGG-16——深度学习的突破性进展。