总体概览:
利用神经网络来进行手写识别就是将输入手写的数据经过一系列分析最终生成判决结果的过程。
使用的神经网络模型如下:
输入数据是像素为28 × 28 = 784的黑白图片(共55000张)
使用10位one-hot编码:
0 -> 1000000000
1 -> 0100000000
2 -> 0010000000
3 -> 0001000000
4 -> 0000100000
5 -> 0000010000
6 -> 0000001000
7 -> 0000000100
8 -> 0000000010
9 -> 0000000001
只需识别神经网络输出结果向量中对应第几列的值最大,对应的索引即为识别结果。
tf.layers.conv2d(
inputs,
filters,
kernel_size,
strides=(1, 1),
padding='valid',
activation=None,
)
在这个例子中第一层卷积层定义如下:
# 第1层卷积
conv1 = tf.layers.conv2d(
inputs=input_x_images, # 形状28*28*1
filters=32, # 输出深度为32
kernel_size=[5, 5], # 滤波器在二维的大小
strides=1, # 采样步长
padding='same', # 表示输出大小不变,因此需要在外围补零两圈
activation=tf.nn.relu
) # 输出形状变为[28, 28, 32]
tf.layers.max_pooling2d(
inputs,
pool_size,
strides,
)
在这个例子中第一层池化层定义如下:
# 第1层池化(亚采样)
pool1 = tf.layers.max_pooling2d(
inputs=conv1, # [28,28,32]
pool_size=[2, 2],
strides=2,
) # 形状[14, 14, 32]
第一池化层之后的第二卷积层定义如下:
# 第2层卷积(亚采样)
conv2 = tf.layers.conv2d(
inputs=pool1, # 形状[14,14,32]
filters=64, # 输出深度为64
kernel_size=[5, 5], # 滤波器在二维的大小
strides=1, # 采样步长
padding='same', # 表示输出大小不变,因此需要在外围补零两圈
activation=tf.nn.relu
) # 形状[14, 14, 64]
第二卷积层之后的第二池化层定义如下:
# 第2层池化(亚采样)
pool2 = tf.layers.max_pooling2d(
inputs=conv2, # [14,14,64]
pool_size=[2, 2],
strides=2,
) # 形状[7, 7, 64]
之后进行平坦化操作:
flat = tf.reshape(pool2, [-1, 7 * 7 * 64]) # 形状[7*7*64, ]
tf.layers.dense(
inputs,
units,
activation=None,
)
1024个神经元的全连接层定义如下:
dense = tf.layers.dense(inputs=flat, units=1024, activation=tf.nn.relu)
丢弃50%操作:
dropout = tf.layers.dropout(inputs=dense, rate=0.5)
10个神经元的全连接层,使用线性激活函数:
logits = tf.layers.dense(inputs=dropout, units=10) # 输出 [1,1,10]
利用最小化误差来优化神经网络的参数:
# 计算误差(计算Cross entropy(交叉熵),再用softmax计算百分比概率)
loss = tf.losses.softmax_cross_entropy(onehot_labels=output_y, logits=logits)
# Adam优化器来最小化误差,学习率0.001
train_op = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)
图的结构定义好之后使用Session启动。
训练结果: