1. MNIST 数据集的下载及其介绍
下载地址为:点击打开链接
内容:下载下来的数据集被分成两部分:60000行的训练数据集(mnist.train)和10000行的测试数据集(mnist.test)。每一个MNIST数据单元有两部分组成:一张包含手写数字的图片和一个对应的标签。训练数据集的图片是 mnist.train.images ,训练数据集的标签是 mnist.train.labels。每一张图片包含28X28个像素点。我们把这个数组展开成一个向量,长度是 28x28 = 784。因此,在MNIST训练数据集中,mnist.train.images 是一个形状为 [60000, 784] 的张量,第一个维度数字用来索引图片,第二个维度数字用来索引每张图片中的像素点。在此张量里的每一个元素,都表示某张图片里的某个像素的强度值,值介于0和1之间。相对应的MNIST数据集的标签是介于0到9的数字,用来描述给定图片里表示的数字。在次教程中,我们使标签数据是"one-hot vectors"。 一个one-hot向量除了某一位的数字是1以外其余各维度数字都是0。所以在此教程中,数字n将表示成一个只有在第n维度(从0开始)数字为1的10维向量。比如,标签0将表示成([1,0,0,0,0,0,0,0,0,0,0])。因此, mnist.train.labels 是一个 [60000, 10] 的数字矩阵。
MNIST数据集内容展示:
(debug 就可以看到了)
2. cnn 网络结构
input layer +
convolutional layer1 + max pooling +
convolutional layer2 + max pooling +
fully connected layer1 + dropout +
fully connected layer2 +
output layer
3. 程序详解
# load MNIST data
import tensorflow.examples.tutorials.mnist.input_data as input_data
# 启用 one_hot 编码
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
# start tensorflow interactiveSession
import tensorflow as tf
sess = tf.InteractiveSession()
# weight initialization
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
# bias initialization
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
# convolution
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
# pooling
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
# Create the model
x = tf.placeholder("float", [None, 784])
y_ = tf.placeholder("float", [None, 10])
W = tf.Variable(tf.zeros([784, 10]))
# b:[ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
b = tf.Variable(tf.zeros([10]))
# x: None * 784 W:784 * 10 b:1 * 10
y = tf.nn.softmax(tf.matmul(x, W) + b)
# first convolutinal layer
# 32 个卷积核,代表 32 个特征
w_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
# -1 根据 x 的具体大小而定
x_image = tf.reshape(x, [-1, 28, 28, 1])
# b_conv1:1 * 32
# tf.nn.conv2d(input, w, strides, padding)
# 其中 input 为输入,格式为[batch, height, width, channels], 分别为【输入的批次数量、图像的高(行数)、宽(列数)、通道(彩色为3,灰色为1)】
# 第二个参数filter:相当于CNN中的卷积核,它要求是一个Tensor,具有[filter_height, filter_width, in_channels, out_channels]这样的shape,
# 具体含义是[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],要求类型与参数input相同,有一个地方需要注意,第三维in_channels,就是参数input的第四维
h_conv1 = tf.nn.relu(conv2d(x_image, w_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
# second convolutional layer
# 64 个卷积核,代表 64 个特征
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)
# densely connected layer
# 经过第一次卷积池化后每张图片变成 14 × 14
# 经过第二次卷积池化后每张图片变成 7 × 7
w_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
# h_pool2_flat 二维
# tf.matmul 矩阵乘法
# h_fcl:-1 * 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
# Dropout是指在模型训练时随机让网络某些隐含层节点的权重不工作,不工作的那些节点可以暂时认为不是网络结构的一部分,
# 但是它的权重得保留下来(只是暂时不更新而已),因为下次样本输入时它可能又得工作了。训练神经网络模型时,如果训练样本较少,
# 为了防止模型过拟合,Dropout可以作为一种trikc供选择。
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
# readout layer
w_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
# output layer
# tf.matmul 矩阵点乘
# y_conv -1 * 10
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, w_fc2) + b_fc2)
# train and evaluate the model
# loss fuction:交叉熵, 因为上面使用的是 SoftMax,所以这里的交叉熵具体来说是 SotfMax Loss
cross_entropy = -tf.reduce_sum(y_ * tf.log(y_conv))
# train_step = tf.train.AdagradOptimizer(1e-4).minimize(cross_entropy)
train_step = tf.train.GradientDescentOptimizer(1e-4).minimize(cross_entropy)
# 将每张图片预测到的数序和它本身的label做对比,相同为 True,相反为 False
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
# 将 False 变成 0,True变成 1,并把所有结果求和
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
# tensorflow 中变量初始化
sess.run(tf.global_variables_initializer())
for i in range(20000):
# 从 55000 条数据中抽取 50 条数据训练网络
batch = mnist.train.next_batch(50)
if i%100 == 0:
train_accuracy = accuracy.eval(feed_dict={x:batch[0], y_:batch[1], keep_prob:1.0})
print("step %d, train accuracy %g" %(i, train_accuracy))
# 训练网络的时候开启 dropout
train_step.run(feed_dict={x:batch[0], y_:batch[1], keep_prob:0.5})
# 测试网络的时候关闭 dropout
print("test accuracy %g" % accuracy.eval(feed_dict={x:mnist.test.images, y_:mnist.test.labels, keep_prob:1.0}))
4. 结果展示:
5. 对 MNIST 的浅显理解,如有错误请指正,共同学习。
6. 参考:
http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_beginners.html