赞
踩
本文以CIFAR-10为数据集,基于Tensorflow介绍了CNN(卷积神经网络)图像分类模型的构建过程,着重分析了在建模过程中卷积层、池化层、扁平化层、全连接层、输出层的运算机理,以及经过运算后图像尺寸、数据维度等参数的变化情况。
CIFAR-10数据集由60000张彩色图片构成,其中包括50000张训练集图片、10000张测试集图片,每张图片的shape为(32,32,3),即图片尺寸为32*32,通道数为3;所有图片可以被分为10类,包括:
官网截图如下所示:
TensorFlow™ 是一个使用数据流图进行数值计算的开放源代码软件库,其API可在Python、C++、Java、Go、Swift (Early Release)语言中调用,其中Python API是目前最完整且易用的。TensorFlow擅长训练深度神经网络,被认定为是神经网络中最好用的库之一。通过使用TensorFlow我们可以快速入门神经网络, 大大降低了深度学习(也就是深度神经网络)的开发成本和开发难度。
Tensorflow使用数据流图进行数值计算,图中的节点代表数学运算,图中的边代表在这些节点之间传递的多维数组(张量)。在使用其构建模型时,先搭建好流图结构——类似于铺好管道,然后再加载数据——向管道中注水,让数据在各节点计算、沿各管道流动;数据在流图中计算、传递时采用多维数组(张量)的形式,因此在Tensorflow中参与计算的均为数组数据类型。
本文使用Tensorflow构建简单的CNN图像多分类模型,其由3个卷积(含激活函数)与池化层、1个扁平层、3个全连接层、1个输出层构成,示意图如下所示:
图像数据经过标准化(normalize)、ont-hot编码等预处理后形成的4D张量,本文输入层张量shape为[batch, height, width, channels]。
卷积层与池化层的作用在于:
1. invariance(不变性),这种不变性包括translation(平移),rotation(旋转),scale(尺度);
2. 保留主要的特征同时减少参数(降维,效果类似PCA)和计算量,防止过拟合,提高模型泛化能力。
卷积层计算的过程如下图所示:
最左侧为输入层图像(加padding后的shape:(7,7,3)),中部为2个卷积核W0、W1及与之相对应的Bias b0、b1,最右侧为输入图像与核w0、w1进行卷积计算后的结果——前者对应于上部图、后者对应于下部图,卷积计算得到的结果即为feature map。每个卷积核与上层图像进行卷积运算后均会得到1个feature map。对于3通道图像,参考本图,卷积运算的过程如下:
1. 输入图像的每个通道分别从左上角开始,每次取与卷积核大小相同的部分(称之为patch),与卷积核对应部分分别相乘后再相加(内积运算);如R通道与W0的最上部核(0核)对应元素相乘再相加得到0,G通道与w0的1核做内积运算得到2,B通道与w0的2核做内积运算后得到0;
2. 内积运算得到的结果相加,再加上w0的bias值(b0),得到feature map左上的元素值;即0+2+0+1=3;
3. 按照指定步长移动卷积核,直至输入图像被整个覆盖,得到最终的feature map;本图中步长(stride)为(2,2)。
这里是动图:
Tensorflow实现卷积运算的函数为:
tf.nn.conv2d(
input,
filter,
strides,
padding,
use_cudnn_on_gpu=True,
data_format='NHWC',
dilations=[1, 1, 1, 1],
name=None
)
参数说明如下:
ints
列表;默认为[1,1,1,1]。长度为4的一维张量,每个input
维度的膨胀系数; 如果设置为k> 1,则每个该维度上的过滤器元素之间会有k-1个跳过的单元格; 维度顺序由data_format
的值决定; 在Dilations中批次和深度尺寸必须为1;输入图像经过卷积运算后,其高度、宽度变为——
‘SAME’ 类型的padding,其输出的height和width计算如下:
out_height = ceil(float(in_height) / float(strides[1])) ceil:向上取整
out_width = ceil(float(in_width) / float(strides[2]))
‘VALID’类型的padding, 其输出的height和width计算如下:
out_height = ceil(float(in_height – filter_height + 1) / float(strides[1]))
out_width = ceil(float(in_width – filter_width + 1) / float(strides[2]))
验证该函数的文章,请看这里。
池化层、全连接层等通过线性运算构建的是线性模型,该模型的表达能力有限;激活函数能够加入非线性因素,从而使模型的表达能力得到极大提升。常用的激活函数有Tanh函数 、ReLU函数 、Leaky ReLU函数 、Maxout函数 等,本文使用ReLU函数作为激活函数。
Tensorflow中的relu激活函数为:
tf.nn.relu(
features,
name=None
)
参数说明如下:
池化层与卷积层的作用、计算方法类似,也有池化filter、步长、填充方式等参数,所不同的是,池化计算比较简单,常取filter覆盖部分的最大值、或者均值,分别称之为最大池化、平均池化,最大池化的示意图如下所示:
最大池化的filter shape为(2,2), 步长也为(2,2),每个filter滑动覆盖处取最大值,得到右侧所示的结果。
Tensorflow实现最大池化运算的函数为:
tf.nn.max_pool(
value,
ksize,
strides,
padding,
data_format='NHWC',
name=None
)
参数说明如下:
上层feature map经池化运算后,其batch、channels均不发生变化,只有height、width会发生变化,输出height、width计算方式同卷积层。
将上一层得到的全部feature map拉直成列向量,作为全连接网络的输入。拉直方式为height*width*channels。
Tensorflow实现扁平化层运算的函数为:
tf.contrib.layers.flatten(
inputs,
outputs_collections=None,
scope=None
)
参数说明如下:
图像分类模型训练完成后,本层返回张量的shape(主要是k)就确定了,从而限定了模型预测时输入图像的尺寸——因为在模型确定的情况下,卷积层、池化层等结构、数量均不再改变,预测图像与训练图像尺寸一致时,经卷积、池化等运算后,扁平化输出shape与模型一致;预测图像与训练图像尺寸不一致时,经卷积、池化等运算后,扁平化输出的shape与模型不一致,从而无法继续运算。这也是迁移学习时,预训练模型均约定输入图像height、width的原因。
从该层开始,分类模型的网络结构类似于“多层前馈神经网络”。
全连接层在整个卷积神经网络中起到“分类器”的作用、也是模型表示能力的“防火墙”。全连接层的运算形如X*W+b,X*W为矩阵乘法,其中X为输入2维数组(shape为[batch_size, k]),W为权重2维数组(shape为[k,out_k]),b为偏置,W的第2个元素(out_k)决定了全连接层运算后输出的2维数组形状(shape为[batch_size, out_k])。
由于全连接层参数冗余(仅全连接层参数就可占整个网络参数80%左右),需要使用tf.nn.dropout来随机丢弃一些节点,或者使用一些性能优异的网络模型如ResNet和GoogLeNet等来取代全连接层融合学到的深度特征。
Tensorflow中实现全连接层的函数为:
tf.layers.dense(
inputs,
units,
activation=None,
use_bias=True,
kernel_initializer=None,
bias_initializer=tf.zeros_initializer(),
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
trainable=True,
name=None,
reuse=None
)
参数说明如下:
Tensorflow中的Dropout函数为:
tf.nn.dropout(
x,
keep_prob,
noise_shape=None,
seed=None,
name=None
)
参数说明:
输出层运算与全连接层类似,只是在设定运算参数时输出节点数量需与分类标记数量相一致,并且在运算完成后再使用tf.nn.softmax函数,得到测试图像属于各分类的概率,该所有概率值之和为1。
Tensorflow中的tf.nn.softmax函数如下所示:
tf.nn.softmax(
logits,
axis=None,
name=None,
dim=None
)
参数说明如下:
按照输入层、卷积层与池化层(共3层)、扁平化层、全连接层(共3层)、输出层的顺序搭建好模型,以交叉熵均值作为cost,以Adam优化算法寻找全局最优点,以cost、Accuracy(分类准确率)作为评估模型的指标,各层参数设置如下图所示:
补充说明如下:
训练构建好的CNN图像分类模型时,单张图片用3D数组表示,多张图片用4D数组表示,经过卷积、激活函数、池化、扁平化、全连接、Dropout等运算,其batch、height、width、channels、feature map数量、节点数量、数据shape有的会发生变化,有的不会发生变化,如下表所示:
运算名称 | batch | 图像height | 图像width | 图像channels | feature map数量 | 节点数量 | 数据shape |
---|---|---|---|---|---|---|---|
卷积 | 不改变 | 会改变 | 会改变 | (首次卷积后变成1) | 会改变 | - | 4D张量 |
激活函数 | 不改变 | 不改变 | 不改变 | - | 不改变 | - | 4D张量 |
池化 | 不改变 | 会改变 | 会改变 | - | 不改变 | - | 4D张量 |
扁平化 | 不改变 | 不改变 | 不改变 | - | 不改变 | 不改变 | 2D张量 |
全连接 | 不改变 | - | - | - | - | 会改变 | 2D张量 |
Dropout | 不改变 | - | - | - | - | 会改变 | 2D张量 |
使用CIFAR-10训练集进行训练,在训练集和测试集上的准确率均为0.73,如下图所示:
本文以CIFAR-10数据集为例,使用Tensorflow构建了简单的CNN图像分类模型,该模型包含输入层、卷积与池化层、扁平化层、全连接层、输出层,这些层均是构建CNN分类模型必要且重要的层;训练后分类模型的准确率虽然不够高,但本文重在分析各层运算时图像数据shape的变化及其它尺寸数据的改变情况。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。