mnist手写数字识别

在实现整个mnist手写数字识别之前,我们先对整个识别过程推导一遍。

首先,假设我们已经拥有一个训练完成的模型,设样本为X=[x_1{},x_2{},...,x_{784}],其中向量的各元素均为mnist数据集每张28*28图片的灰度值,一共784个元素 。

现在,令样本X为第i类的特征的加权和为feature_{i}=\sum_{j=1}^{784}w_{ij}x_{j}+b_{i}

其中,w_{ij}为样本X中第j个元素的值对样本X为第i类是的影响程度,也就是权值,b_{i}指如果在数据整体中,第i类较多,则b_{i}较大。

现在已经求得样本X为第i类时的特征的加权和,下一步就是将这些加权和计算softmax,也就是都计算一个exp函数,然后进行标准化(让所有类别输出的概率值和为1)。如下:

sofemax(feature_i)=normalize(exp(feature_i))

X_i为样本X是第i类的概率,则

X_i=(softmax(feature_i))/(\sum_{i=1}^{10}softmax(feature_i))=softmax(feature_i)

网格图如下:

那么预测结果y_1=softmax(x_1w_11+x_2w_12+...+x_jw_1j+b_1)y_2=softmax(x_1w_21+x_2w_22+...+x_jw_2j+b_2),...,y_i=softmax(x_1w_{i1}+x_2w_{i2}+...+x_jw_{ij}+b_i),也即Y=softmax(WX+B),所以我们只用通过学习求得权值矩阵和偏置矩阵B,以及利用一个softmax函数,即可完成对手写数字的识别。

扫描二维码关注公众号,回复: 2419189 查看本文章

代码如下:其中loss函数采用的cross-entropy,优化算法是随机梯度下降SDG,也即mini-batch gradient descent,mini-batch下降算法。其中loss函数用来评价模型的训练结果,优化算法主要可以加快算法向最优解方向收敛,同时在一定程度上避免陷入局部最优,当然不能完全避免。

from tensorflow.examples.tutorials.mnist import input_data
mnist=input_data.read_data_sets("C:/Users/PengFeihu/Desktop/mnist",one_hot=True)

print(mnist.train.images.shape,mnist.train.labels.shape)
print(mnist.test.images.shape,mnist.test.labels.shape)
print(mnist.validation.images.shape,mnist.validation.labels.shape)

import tensorflow as tf
sess = tf.InteractiveSession() #创建新的会话并将该会话设置成为默认会话
x = tf.placeholder(tf.float32, [None,784]) #设置输入样本大小,None表示不限样本数量,784表示每个样本包含784个灰度值

W=tf.Variable(tf.zeros([784,10]))
b=tf.Variable(tf.zeros([10])) #将权值矩阵和偏置矩阵初始设置为0

#接下来实现softmax regression算法,其中tensorflow中的softmax regression函数可以自动实现forward和backward
y=tf.nn.softmax(tf.matmul(x,W)+b)

#定义loss function,采用的是cross-entropy
y_ = tf.placeholder(tf.float32,[None,10])
cross_entropy=tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y),
                                           reduction_indices=[1] ))

#优化器,步长0.5,loss function为cross_entropy
train_step = tf.train.GradientDescentOptimizer(0.5).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({x:batch_xs, y_:batch_ys})

 在以上基础上,再加一层隐含层,通过多层神经网络(多层感知器MLP)实现mnist手写数字的识别。其中hidden层的激活函数选择ReLU,优化器使用adagrad,同时为了演示避免过拟合的方法,对隐含层节点输出进行了dropout处理。保留的节点比率为0.75。代码如下:

from tensorflow.examples.tutorials.mnist import input_data
mnist=input_data.read_data_sets("C:/Users/PengFeihu/Desktop/mnist",one_hot=True)
import tensorflow as tf
sess = tf.InteractiveSession()

in_units = 784  #输入节点数
h1_units = 300  #隐含层节点数
W1 = tf.Variable(tf.truncated_normal([in_units, h1_units], stddev = 0.1))   #用截断的正态分布初始化隐含层权值
b1 = tf.Variable(tf.zeros([h1_units]))  #将偏置全都置0
W2 = tf.Variable(tf.zeros([h1_units, 10]))
b2 = tf.Variable(tf.zeros([10]))

x = tf.placeholder(tf.float32, [None, in_units])
keep_prob = tf.placeholder(tf.float32)  #保留节点的比率

#定义隐含层输出和输出层输出
hidden1 = tf.nn.relu(tf.matmul(x,W1) + b1)
hidden1_drop = tf.nn.dropout(hidden1, keep_prob)
y = tf.nn.softmax(tf.matmul(hidden1_drop,W2)+b2)

#定义损失函数和优化器
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y),
                                              reduction_indices = [1])) #loss函数依旧使用交叉信息熵cross_entropy
train_step = tf.train.AdagradOptimizer(0.3).minimize(cross_entropy) #优化算法使用了Adagrad,学习速率为0.3.之前使用的SGD

#开始训练,注意在训练中加入了keep_prob参数
tf.global_variables_initializer().run()
for i in range(3000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    train_step.run({x: batch_xs, y_: batch_ys, keep_prob: 0.75})    #保留0.75的隐含层节点的输出

#对模型进行准确率评价
correct_prediction = tf.equal(tf.argmax(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,
                     keep_prob: 1.0}))

在代码最后有一个准确率评价,这个评价最后将会打印出模型预测的准确率。有一个疑问:accuracy.eval({x: mnist.test.images, y_:mnist.test.labels, keep_prob: 1.0})的作用是什么?是将测试集导入模型并返回和labels比对的准确率吗?

猜你喜欢

转载自blog.csdn.net/shnu_pfh/article/details/81178039