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 i0 == 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
