对于每一个初学深度学习的小伙伴, Mnist手写数字识别问题非常经典, tensorflow官网教程首先就介绍了分别使用单隐层网络(准确率约91%)和多层卷积网络(准确率约99.2%)来解决这个问题. luffy也入了深度学习的坑, 刚刚依照官网步骤分别实现了两种方法, 源代码见github, 对于卷积神经网络方法有种似懂非懂的感觉(其实就是不懂(>_<)), 所以写此博客, 一遍分析, 一遍记录心得.
Mnist问题, 在我看来属于"麻雀虽小五脏俱全", 很有分析的价值.下面进行一一梳理.
基本流程
数据处理
构建模型
损失函数
训练模型
测试模型
附上源代码
'''
构建一个多层卷积网络(输入层+卷积池化x2+全连接层x2)
参照Tensorflow中文社区-MNIST进阶-编写
'''
#encoding=utf-8
import tensorflow as tf
import input_data
#interactivesession, 允许tensorflow在运行图的时候, 插入一些计算图, 不然只能先构建整个计算图, 然后启动图, 可对比Mnist_Primary的做法
sess = tf.InteractiveSession()
#数据, 如果比赛的话需要自己处理
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)
###################### 构建计算图###############
#占位符, 运行session时填入具体的值
x = tf.placeholder("float", shape = [None, 784])
y_ = tf.placeholder("float", shape = [None, 10]) #真实值, 用于计算交叉熵
#权重初始化
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1) #用截断的正态分布初始化tensor, 标准差0.1
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape) #使用常数0.1初始化tensor
return tf.Variable(initial)
#卷积和池化
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1,1,1,1], 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')
#第一层卷积
W_conv1 = weight_variable([5,5,1,32]) #patch大小5x5, 输入通道数1, 输出通道数32
b_conv1 = bias_variable([32]) #每一个输出通道对应一个偏置量
x_image = tf.reshape(x, [-1, 28, 28, 1]) #第二 三维代表图像宽高, 第四维代表通道数, 灰度图为1
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]) #不是很明白第三 四维为什么是32和64
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) +