从MNIST学习卷积神经网络

卷积神经网络包括输入层、卷积层、池化层、全连接层、输出层。
其中卷积层、池化层为卷积神经网络的重点,在一个卷积网络中,卷积层和池化层可以有多层。

卷积层

参数:卷积核尺寸 、滑动窗口步长、边缘填充(用来弥补一些边界特征的损失)、卷积核个数
卷积计算如下图所示:
卷积层计算原始图片的特征图卷积所得到的特征图尺寸的计算公式:
在这里插入图片描述
H1、W1为输入图的长和宽;H2、W2为输出特征图的长和宽;F为卷积核的长和宽;S为滑动窗口的步长;P为边界填充(共加了几圈0)

池化层

由卷积层所提取到的特征图过于庞大,由池化层对特征图进行压缩处理,池化层不涉及参数优化,只是对特征图中的特征值进行筛选。一般采用最大池化(max_pool),选取滑动窗口中的最大值作为特征值。

mnist手写数字识别

卷积层+池化层

卷积网络中的参数定义:

# 卷积核定义
def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)
# 偏置值定义
def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

卷积函数、池化函数定义:

# 卷积层函数
# 滑动窗口步长为1步,对图片进行边缘填充
def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

# 池化函数
# 滑动窗口尺寸为[1, 2, 2, 1],滑动步长为2,边缘填充
def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

这里 padding=‘SAME’ 是指进行边缘填充,若为VALID则表示不进行边缘填充。strides=[1, 2, 2, 1]指步长为2,其中第一位和最后一位固定为1。
卷积层操作:

# 第一层卷积层
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
# 进行卷积计算, relu作为激活函数
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
# 最大池化操作
h_pool1 = max_pool_2x2(h_conv1)

# 第二层卷积层
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)

第一层卷积层的卷积核尺寸设为[5, 5, 1, 32],意思为第一层有10个5*5的卷积核对输入图像进行卷积操作,这里1为图像通道数,与输入图相同。

手动计算最后所得特征图尺寸

采用上面所提到的特征图尺寸计算公式,可以计算经过两次(卷积+池化)操作后所得到的特征图的尺寸。
在这里插入图片描述

全连接层

全连接层为两层,第一层将前面所得到的特征图转化为多维向量

# 第一层全连接层
# 输出为1024维的向量
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)
# 使用Dropout, keep_prob是一个占位符,训练时为0.5, 测试时为1
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

这里的 7 * 7 * 64 即为我们上面手动所得到的一张特征图的尺寸转化为多维向量的结果。
在这里使用了Dropout,这是防止神经网络过拟合的一种手段,在每一步训练时,以一定概率“去掉”网络中的某些连接,但这种去除不是永久性的,只是在当前步骤中去除,并且每一步的连接都是随机去除的。
在第二层全连接层中将所得的多维向量转化为10个类别

# 第二层全连接层
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2

到这里一个用于进行MNIST手写数字识别的卷积神经网络建立完毕。

接下来建立交叉熵损失,使用优化算法(这里使用Adam算法)对该网络进行训练。

扫描二维码关注公众号,回复: 11018346 查看本文章
# 定义交叉熵损失
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
# 定义梯优化算法
train_step = tf.train.AdamOptimizer(0.01).minimize(cross_entropy)

代码地址:

https://github.com/xwzhang0724/WEI_Code/blob/master/mnist05.py

若有不妥,请多见谅!

发布了3 篇原创文章 · 获赞 0 · 访问量 65

猜你喜欢

转载自blog.csdn.net/weixin_44762772/article/details/105660324
今日推荐