前言

这是之前刚接触深度学习时,利用卷积神经网络进行图像分类的小实践。
主要参考资料为
https://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/deep_cnn.html
<https://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/deep_cnn.html>。
Tensorflow安装方法见https://tensorflow.google.cn/install/install_linux
<https://tensorflow.google.cn/install/install_linux>。
由于工作量和时间问题,基础理论部分不再赘述,有时间再补充。

实验目的

1.熟悉TensorFlow以及完成其下载和安装
2.熟悉卷积神经网络

实验环境

1.操作系统:Ubuntu 14.04,
2.深度学习平台:TensorFlow 0.8.0
3.编程语言:python 2.7

实验步骤


本实验的目标是构建用于识别图像的相对小的卷积神经网络(CNN),因为CIFAR-10数据集的复杂程度足以用来检验TensorFlow中的大部分功能,并可将其扩展为更大的模型。同时由于模型较小所以训练速度很快,比较适合用来测试新的想法,检验新的技术。所以选用CIFAR-10数据集实现图片的分类。

1. CIFAR-10数据集简介

CIFAR-10数据集由60000个32x32彩色图像组成,包括10个类别,每个类别有6000个图像。有50000个训练图像和10000个测试图像。

数据集分为五个训练批次和一个测试批次,每个批次有10000个图像。测试批次包含来自每个类的正好1000个随机选择的图像。训练批次以随机顺序包含剩余的图像,但是一些训练批次可能包含来自一个类的更多图像。在他们之间,训练批次正好包含每个类别的5000个图像。
下图是数据集中的类,以及每个类的10个随机图像:




2. 代码组成

本实验的代码源于TensorFlow的官方GitHub,地址为:
https://github.com/tensorflow/models/blob/master/tutorials/image/cifar10
<https://github.com/tensorflow/models/blob/master/tutorials/image/cifar10>。
包含的文件和作用如表1所示:

表1 代码文件和作用


代码文件 作用
Cifar10_input.py 读取本地CIFAR-10的二进制文件的内容
Cifar10.py 建立CIFAR-10的模型
Cifar10_train.py 在CPU或GPU上训练CIFAR-10的模型
Cifar10_multi_gpu_train.py 在多GPU上训练CIFAR-10的模型
Cifar10_eval.py 评估CIFAR-10模型的预测性能
注:由于设备的限制,本实验只在CPU上进行训练,因此不会使用到Cifar10_multi_gpu_train.py文件。

3. 准备实验环境和下载数据集

本实验使用的操作系统为Ubuntu 14.04,Python版本为2.7,将CIFAR-10数据集下载到本地,可以提前在官网(
http://www.cs.toronto.edu/~kriz/cifar.html
<http://www.cs.toronto.edu/~kriz/cifar.html>)下载。
在本实验中,在终端执行Cifar10_train.py后,会自动在本地搜索CIFAR-10数据集,如果没有搜索到,会自动转到官网下载。

4. 建立CIFAR-10模型

CIFAR-10 网络模型部分的代码位于 cifar10.py。完整的训练图中包含约765个操作。但是通过下面的模块来构造训练图可以最大限度的提高代码复用率:
(1)模型输入: inputs() 和 distorted_inputs() 分别添加读取和预处理CIFAR图像以进行评估和训练的操作;
(2)模型预测: inference() 添加对提供的图像执行推理的操作;
(3)模型训练: loss() 和 train() 函数添加计算损失、计算梯度、进行变量更新以及可视化最终结果。

4.1 模型输入

通过 inputs() 和 distorted_inputs()函数建立输入模型,这两个函数会从CIFAR-10二进制文件中读取图片文件。
图片文件的处理流程如下:

* 图片会被统一裁剪成24x24像素大小,裁剪中央区域用于评估或随机裁剪用于训练;
* 图片会进行近似的白化处理,使得模型对图片的动态范围变化不敏感。
对于训练,另外采取了一系列随机变换的方法来人为的增加数据集的大小:
通过tf.image.random_flip_left_right(distorted_image) 函数对图像进行随机的左右翻转;
通过tf.image.random_brightness(distorted_image,max_delta=63) 函数随机变换图像的亮度;
通过tf.image.random_contrast(distorted_image,lower=0.2,、upper=1.8) 随机变换图像的对比度。

4.2 模型预测

由inference()函数构造模型预测的流程,该函数会添加必要的操作步骤用于计算预测值的 logits,其对应的模型组织方式如表2所示:

表2 模型组织方式


Layer 名称 描述
conv1 实现卷积和修正线性激活
pool1 最大池化(max pooling)
norm1 局部响应归一化
conv2 实现卷积和修正线性激活
norm2 局部响应归一化
pool2 最大池化(max pooling)
local3 基于修正线性激活的全连接层
local4 基于修正线性激活的全连接层
softmax_linear 进行线性变换以输出logits
描述模型建立过程中经过的步骤如下图所示。


这里简单分析下第一层卷积,它由一个卷积接一个max pooling完成。卷积在每个5x5的patch中算出64个特征。卷积的权重张量形状是[5, 5,
3, 64],前两个维度是patch的大小,接着是输入的通道数目,最后是输出的通道数目。
使用tf.nn.conv2d(images,kernel,[1,1,1,1],padding='SAME')
函数进行卷积滑动,对于每一个输出通道都有一个对应的偏置量,与卷积值相加后作为激励函数ReLU的输入,ReLU函数的输出即conv1的输出。

pool1=tf.nn.max_pool(conv1,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME',name='pool1')
,模板是3*3,移动步长2*2,有重叠的pooling。pooling层之后有个局部响应归一化norm1(
tf.nn.local_response_normalization,简写为tf.nn.lrn)。
损失函数:loss=cifar10.loss(logits,labels),具体使用
cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits(logits,labels,name='cross_entropy_per_example')
计算交叉熵。


4.3 模型训练

使用Softmax回归将softmax非线性应用于网络的输出,并且计算归一化的预测值和标签的1-hot
编码的交叉熵。在正则化过程中,对所有学习变量应用权重衰减损失。模型的目标函数是求交叉熵损失和所有权重衰减项的和,即loss()函数的返回值。

实验分析及结论

1. 启动并训练模型

建立好模型后,在终端将路径切换到cifar10_train.py目录下,输入命令python cifar10_train.py
启动训练过程。终端输出的模型训练过程如下图所示。



可以看出,每训练10步后,打印输出总损失值loss,随着迭代步数的增加,损失值loss总体的趋势是不断较小,最终经过20000次迭代后,损失值固定在0.72,至此一个CIFAR-10模型训练完成。
可以通过TensorBoard获得更多模型训练的信息。模型会创建一个记录所有训练过程的文件,在终端将路径切换到此文件目录下,输入命令tensorboard
–logdir=文件的路径,如下图所示。

在浏览器打开链接http://0.0.0.0:6006,部分可视化信息如下图所示。




2. 评估模型

用测试集来评估训练模型的性能。脚本文件cifar10_eval.py对模型进行评估,利用 inference()
函数重构模型,并使用CIFAR-10测试集的10,000张图片进行测试。
在终端将路径切换到cifar10_eval.py目录下,输入以下命令python cifar10_eval.py启动评估过程。终端窗口输出如下图所示。


评估脚本周期性的返回precision @ 1= presion,本实验返回的准确率是83%。