手写数字分类可以说是机器学习的“Hello world”了。先前在《Python深度学习》中有使用Keras实现手写数字分类,具体可以看看Keras实现手写数字分类
在本文中会使用两种方式实现手写数字分类,一种是Softmax Regression,第二种是多层感知机(即全连接网络)
神经网络的训练分四个步骤:1)定义算法公式;2)定义损失函数和选择优化器;3)训练步骤;4)对模型进行准确率评估
数据集介绍
mnist是一个经典的手写测试集,包含6000万张训练图片和10000张测试图片,每张图片的大小为28*28。
对于图片数据的处理,将2828的图片展开成7841,对标签采用one_hot编码,即标签是一个10维的向量,对于标签0,即为[1,0,0,0,0,0,0,0,0,0]。
TensorFlow简介
相比Keras,TensorFlow的使用没有那么直观,有以下几点需要说明
2.Session
为了能够实现一个计算流程就需要一个graph来表示这个流程,而为了能够执行这个图就需要一个会话(Session)来启动这个图,这个过程相当于graph是画好的一张图,然后我用一个Session来执行这个图。
Session的方法run(),这里详细的介绍一下run的使用方法。其作用是Runs operations and evaluates tensors in fetches,意思是执行一次Session,其中待执行的内容放在fetches中,这里的fetches目前暂时看成是一些待计算的内容。
常用的两种方式
#方法一
sess = tf.Session()
sess.run(...)
sess.close()
# 方法二
with tf.Session() as sess:
sess.run(...)
2.常用函数
tf.reduce_mean() #计算平均值
tf.reduce_sum() #计算总和
tf.matmul() #计算矩阵乘法
tf.argmax() #计算一个张量中最大值的序号
tf.cast() #转换数据类型
Softmax Regression
本文使用Softmax Regression算法(常用于多任务分类)实现模型。其原理是,将可以判定为某类的特征相加,然后将这些特征转化为判定是这类的概率。关于Softmax Regression算法可以参考SoftmaxRegression详解。
代码详解:
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) #载入数据
#tf.InteractiveSession()主要用于python这种交互场景下
#它和标准的Sessin的唯一区别就是它初始化自己是default的Session。
sess = tf.InteractiveSession()
x = tf.placeholder(tf.float32, [None, 784])#创建输入数据存放的地方
w = tf.Variable(tf.zeros([784, 10])) #创建weights的Variable对象
b = tf.Variable(tf.zeros([10])) #创建bias的Variable对象
y = tf.nn.softmax(tf.matmul(x, w) + b) #实现y = Softmax(wx +b)
y_ = tf.placeholder(tf.float32, [None, 10]) #真实的预测值存放的地方
#计算交叉熵
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) #learning rate = 0.5
tf.global_variables_initializer().run() #使用TensorFlow的全局参数初始化器,并运行其run方法
#迭代训练1000次
for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100) #每次随机地从训练集取100个样本
train_step.run({x:batch_xs, y_: batch_ys})
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) #验证预测值与真实值是否相等
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) #计算模型精度
print(accuracy.eval({x: mnist.test.images, y_:mnist.test.labels}))
运行结果
多层感知机
本项目还可以使用多层感知机,即全连接层(在书的第4.4节),《Python深度学习》里面其实就是用的全连接网络(两层隐含层层),这里只用了一层。主要学一下怎么加全连接层。
代码详解
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) #调用数据
sess = tf.InteractiveSession() #创建Session
in_units = 784 #输入节点数
h1_units = 300 #隐含层输出节点数
w1 = tf.Variable(tf.truncated_normal([in_units, h1_units], stddev = 0.1)) #初始化w1
b1 = tf.Variable(tf.zeros([h1_units])) #初始化b1
w2 = tf.Variable(tf.zeros([h1_units, 10])) #初始化w2
b2 = tf.Variable(tf.zeros([10])) #初始化b2
x = tf.placeholder(tf.float32, [None, in_units]) #定义输入x的placeholder
keep_prob = tf.placeholder(tf.float32) #定义dropout的保留节点的比率
hidden = tf.nn.relu(tf.matmul(x, w1) + b1) #创建隐含层
hidden1_drop = tf.nn.dropout(hidden, keep_prob) #设置隐含层的dropout
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])) #交叉熵
train_step = tf.train.AdagradOptimizer(0.3).minimize(cross_entropy) #使用Adagrad优化器
tf.global_variables_initializer().run() #使用TensorFlow的全局参数初始化器,并运行其run方法
#迭代训练3000次
for i in range(3000):
batch_xs, batch_ys = mnist.train.next_batch(100) #每次用100个样本训练
train_step.run({x : batch_xs, y_: batch_ys, keep_prob:0.75}) #训练模型,dropout的参数设为0.75
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(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})) #输出测试集准确率
运行结果