TensorFlow实现卷积神经网络
一 本节课程介绍
1.1 知识点
1、卷积神经网络介绍;
2、TensorFlow实践CNN网络;
二 课程内容
2.1 卷积神经网络基本介绍
卷积神经网络是一种使用卷积结构构建的神经网络模型,其特点是局部感知、权值共享,池化减少参数和多层次结构。
其基本结构包括输入层、卷积层、降采样和全连接输出层。其中每一层都由卷积核对图像进行卷积计算,将计算到的矩阵称称为特征图,特征图在原图像所映射的区域称之为感受野。一般而言,第一个卷积层的感受野大小等于卷积核大小,而之后的卷积层的感受野大小都与之前的每一个卷积核大小和步长有关。下面开始介绍卷积核和步长的基本概念。
2.1.1 卷积核和步长
其中卷积核包括卷积核尺寸、输入通道数和输出通道数。如(5,5,32,64)意思为64个32通道的5*5卷积核和输入进行卷积得到64个卷积结果。其中卷积的计算按照逐个元素相乘再求和的方式进行操作。而每一个卷积移动的长度即为其卷积步长。
在卷积核概念中,还用到了padding。即为了解决卷积操作中图像越来越小和边界信息丢失的问题。Padding分为以下两种:
(1)valid padding:不进行任何处理,只使用原始图像,不允许卷积核超出原始图像边界;
(2)same padding:进行填充,允许卷积核超出原始图像边界,并使得卷积后结果的大小与原来的一致。
2.1.2 pooling池化
池化层的作用在于减少各个特征的维度,以达到减少计算量的目的。一般而言池化层常常位于每个卷积层之后,用来减少计算和防止过拟合的作用。其中池化层的计算方式和卷积层类似,都是各元素相乘相加的方式,不同点在与卷积核的是有着训练参数的,而池化层没有训练参数,目的只是为了减少计算。其中池化层分为以下两个类别:
(1)最大池化(max pooling):从窗口修正图中选取最大的元素;
(2)平均池化(average pooling):从窗口特征图中求出平均
2.1.3 CNN特点
局部感受野:卷积神经网络通过使用卷积核提取局部特征,然后在深层次对不同神经元感受的区域特征进行综合即可以得到全局信息,同时也可以减少连接的数目。
权值共享:在不同的神经元之间共享参数可以减少模型的计算量,而权值共享就是对图像使用相同的卷积核进行卷积操作,这样卷积层的所有神经元即可以检测到图像不同位置的相同特征,其主要的作用也在于检测不同位置的同一类型特征,即可以实现图像的小范围平移,即平移不变性。
三 实验测试
3.1 预定义
首先要导入库:
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
(1)然后读取手写字体的数据集,并将其转为onehot编码,即不同的图像特征使用不同的编码方式表示。
mnist = input_data.read_data_sets('MNIST_data_bak/', one_hot=True)
(2)对计算会话上下文初始化,在TensorFlow中数字的计算依赖于会话的结构:
sess = tf.InteractiveSession()
(3)定义模型中的W变量,符合正太分布的初始化,标准差设为0.1:
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
(4)定义b变量,初始化为常数:
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
(5)定义卷积层函数,其中x为输入的图像数据,w为卷积的参数,其中stride为定义的步长,padding使用same的方式:
def conv2d(x, W):
return tf.nn.Conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
(6)定义池化层函数,其中x为输入的图像数据,w为卷积的参数,其中stride为定义的步长(为了达到压缩数据的目的,使用步长为2),padding使用same的方式:
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
3.2 模型结构搭建
(1)TensorFlow中对于输入和输出需要使用占位符的方式进行建立,因为输入的图像尺寸为2828,故需要将一维的输入向量转为二维的图片结构,即从1784的形式转为原始的28*28的结构。
x = tf.placeholder(tf.float32, [None, 784])
y_ = tf.placeholder(tf.float32, [None, 10])
x_image = tf.reshape(x, [-1, 28, 28, 1])
(2)定义第一个卷积层,这里的[3,3, 1, 32]代表卷积核尺寸为33,1个颜色通道,32个不同的卷积核,然后使用conv2d函数进行卷积操作,并加上偏置项,接着再使用ReLU激活函数进行非线性处理,最后,使用最大池化函数max_pool_22对卷积的输出结果进行池化操作。
W_conv1 = weight_variable([3, 3, 1, 32])
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
(3)定义第二个卷积层,这里的[5,5,32,64]代表卷积核尺寸为55,32个输入通道,64个输出不同的卷积核,然后使用conv2d函数进行卷积操作,并加上偏置项,接着再使用ReLU激活函数进行非线性处理,最后,使用最大池化函数max_pool_22对卷积的输出结果进行池化操作。
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
(4)因为前面经历了两次步长为22的最大池化,所以边长已经只有1/4了,图片尺寸由2828变成了77,经过了两次池化,每次池化变1/2。而第二个卷积层的卷积核数量为64,其输出的tensor尺寸即为77*64。我们使用tf.reshape函数对第二个卷积层的输出tensor进行变形,将其转成一维的向量。然后连接一个全连接层,隐含节点为1024,并使用ReLU激活函数,特征组合。
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
(5)使用softmax激活函数进行分类,对全连接层加和分类即可。
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_conv = tf.nn.softmax(tf.matmul(h_fc1, W_fc2) + b_fc2)
3.3 优化器和损失函数
这里我们使用Adam损失函数,学习率为0.01,使用交叉熵损失用于分类。
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv),
reduction_indices=[1]))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
3.4 模型迭代训练和评估
(1)设置模型计算准确率。
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
(2)模型迭代训练
accuracys=[]
tf.global_variables_initializer().run()
for i in range(1000):
batch = mnist.train.next_batch(50)
if i % 10 == 0:
train_accuracy = accuracy.eval(Feed_dict={x: batch[0], y_: batch[1]})
print("step :%d, |training accuracy :%g" % (i, train_accuracy))
accuracys.append(train_accuracy)
train_step.run(Feed_dict={x: batch[0], y_: batch[1]})
3.5 可视化绘图
根据准确率绘制评估图。
import matplotlib.pyplot as plt
plt.plot(accuracys)
plt.show()
四 思考与作业
(1)尝试调优模型(从学习率、batchsize和模型结构等方面尝试)
(2)尝试使用TensorFlow实现训练生成图片,即输入文字1生成图片1