算法实现过程的详细介绍

  1. 对Minist数据进行加载,利用Tensorflow提供的封装函数
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
  1. 查看一下mnist数据集的情况,可以发现训练集有55000个样本,测试集有10000个样本,同时验证集有5000个样本。每一个样本都有它对应的标注信息。
print(mnist.train.images.shape, mnist.train.labels.shape)
print(mnist.test.images.shape, mnist.test.images.shape)
print(mnist.validation.images.shape, mnist.validation.labels.shape)
  1. 然后我们将2828的手写数字图片展开为784的一维向量,注意这个的确会丢失空间结构,但是由于这个数据集的分类任务比较简单,所以这里可以不考虑空间结构,后面用CNN的话就考虑。这里,我们的训练数据特征是一个55000784的Tensor,第一个维度是图片的编号,第二个维度是图片中像素点的编号。同时,训练数据的Label是一个10维的向量,只有一个值是1,其余是0.这里使用Softmax Regression的算法训练手写数字识别的分类模型,我们的数字是0-9之间的,所以一共有10个类别,最后取各个类别中概率最大的作为结果输出。对于一张图片,我们可以将特征携程 f e a t u r e i = j W i , j x j + b i feature_i=\sum_jW_{i,j}x_j+b_i featurei=jWi,jxj+bi,其中i表示第i类,j表示一张图片的第j个像素, b i b_i bi是bias。然后对所有特征计算softmax,结果如下: s o f t m a x ( x ) = n o r m a l i z e ( e x p ( x ) ) softmax(x)=normalize(exp(x)) softmax(x)=normalize(exp(x)),其中判定为第i类的概率就是 s o f t m a x ( x ) i = e x p ( x i ) j e x p ( x j ) softmax(x)_i=\frac{exp(x_i)}{\sum_jexp(x_j)} softmax(x)i=jexp(xj)exp(xi),我们先对各个类的特征求exp函数,然后再对它们标准化,使得和为1,特征的值越大的类,最后输出的概率也为1,用矩阵的形式来看可以表示为 y = s o f t m a x ( W x + b ) y=softmax(Wx+b) y=softmax(Wx+b)
  2. 载入Tensorflow库,并创建一个新的InteractiveSession,使用这个命令会将这个Session注册为默认的Session,之后的运算也默认跑在这个Session里面,不同session之间的数据和运算都是相互独立的人。接下来创建一个placeholder,表示输入数据的占位符号。
#注册为默认的Session
sess = tf.InteractiveSession()
x = tf.placeholder(tf.float32, [None, 784])
  1. 给Softmax Regression模型中的weights和bias创建Variable对象,并将weights和bias初始化为0,在初始化的时候,由于这里是浅层并且很简单的网络,所以初始化为0,如果对于深层网络,权重初始化是一门大学问了。再定义一下Softmax Regression模型。
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x, W)+b)
  1. 为了训练模型,我们还需要定义损失函数。Loss越小,代表模型的分类结果和真实值的偏差越小,也就是说模型更精确,我们一开始把模型填充了0,所以模型有一个初始Loss,我们的目的是不断将这个Loss缩小,得到一个全局或者局部最优解。对于多分类问题,常用交叉熵损失函数,公式吐下 H y ( y ) = i y i l o g ( y i ) H_{y'}(y)=-\sum_iy'_ilog(y_i) Hy(y)=iyilog(yi),其中y是预测的概率分布, y y' y是真实的概率分布。
    \quad 先定义一个占位符,输入时真实的label,用来计算cross-entropy。这里的y_*tf.log(y)也就是前面公式的 y i l o g ( y i ) y'_ilog(y_i) yilog(yi),tf.reduce_sum也就是求和的 \sum ,而tf.reduce_mean则是对每个batch数据求均值
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y)))

7.接下来定义个优化算法开始训练,这里使用随机梯度下降SGD。定义好优化算法之后,Tensorflow就可以根据我们定义的整个计算图(前面我们定义好的公式已经构成了计算图)自动求导,并根据反向传播算法进行训练,我们直接调用tf.train.GradientDescentOptimizer,并设置学习速率为0.5,优化目标设定为cross-entropy,得到进行,得到进行训练的操作train_step。

train_step = tf.train.GradientDescentOptimizer(0.0005).minimize(cross_entropy)
  1. 下一步使用Tensorflow的全局参数初始化器tf.global_variables_initalizer(),并直接执行它的run方法。
tf.global_variables_initializer().run()
  1. 最后一步,我们开始迭代执行训练操作train_step,这里每次随机从训练集中抽取100条样本构成mini-batch,并feed给placeholder,然后调用train_step对这些样本进行训练。使用一小部分样本进行训练称为随机梯度下降,与全局随机梯度下降对应。
for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    train_step.run(feed_dict={x: batch_xs, y_:batch_ys})
    print(i)
  1. 现在我们已经完成了训练,接下来就对模型的准确率进行验证。
correct_prediction = tf.equal(tf.arg_max(y, 1), tf.arg_max(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(accuracy.eval({x:mnist.test.images, y_:mnist.test.labels}))

最后打印出来的准确率是92%左右。

算法完整代码

#coding=utf-8
#softmax Regression
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
print(mnist.train.images.shape, mnist.train.labels.shape)
print(mnist.test.images.shape, mnist.test.images.shape)
print(mnist.validation.images.shape, mnist.validation.labels.shape)

#注册为默认的Session
sess = tf.InteractiveSession()
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x, W)+b)
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y)))

train_step = tf.train.GradientDescentOptimizer(0.0005).minimize(cross_entropy)
#全局参数初始化
tf.global_variables_initializer().run()

for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    train_step.run(feed_dict={x: batch_xs, y_:batch_ys})
    print(i)

#计算准确率
correct_prediction = tf.equal(tf.arg_max(y, 1), tf.arg_max(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(accuracy.eval({x:mnist.test.images, y_:mnist.test.labels}))