这里使用 MNIST 数据集,它是由几万张 28像素 * 28像素
的手写数字组成。
流程:
- 参数初始化: w,b
- 定义算法公式:y = Softmax(Wx + b)
- 定义 loss function: cross-entropy
- 选定优化器,并指定优化器优化 loss:随机梯度下降SGD
- 随机选取样本,迭代训练
- 在测试集上对准确率进行评测
1. 加载数据集
TensorFlow 已经为我们提供了一个封装,可以直接加载。
1 2 3
| from tensorflow.examples.tutorials.mnist import input_data dataSet = input_data.read_data_sets("MNIST_data/", one_hot=True)
|
查看数据集的情况:
1 2 3
| print(dataSet.train.images.shape,dataSet.train.labels.shape) print(dataSet.test.images.shape,dataSet.test.labels.shape) print(dataSet.validation.images.shape,dataSet.validation.labels.shape)
|
打印结果: 训练集有55000个样本,测试集有10000个样本,验证集有5000个样本。
1 2 3 4 5 6 7 8
| ➜ handswrite_mnist git:(master) ✗ python mnist.py Extracting MNIST_data/train-images-idx3-ubyte.gz Extracting MNIST_data/train-labels-idx1-ubyte.gz Extracting MNIST_data/t10k-images-idx3-ubyte.gz Extracting MNIST_data/t10k-labels-idx1-ubyte.gz (55000, 784) (55000, 10) (10000, 784) (10000, 10) (5000, 784) (5000, 10)
|
我们将在训练集上训练模型,在验证集上检验效果,最后在测试集上评测模型的效果。
2. 准备数据
首先需要将 28*28 的图片转为一维向量。
我们训练的特征
是一个55000*784
的 Tensor,第一个维度是图片的编号,第二个维度是图片中像素点的编号。
我们训练的label
是一个55000*10
的 Tensor,先对 10 种标签进行 one-hot 编码,label 是一个十维向量,数字 0 代表的是 [1,0,0,0,0,0,0,0,0,0]
,数字 n 代表对应位置的值为1。
3. 设计算法
这里使用 Softmax Regression 算法来训练分类模型:
当我们的模型对一张图片进行预测时,Softmax Regression 会对每一种类别估算一个概率,最后取概率最大的那个数字作为模型的输出结果。
原理:将可以判定为某类的特征相加,然后将这些特征转化为判定时这一类的概率。
我们可以将这些特征写成以下公式:
feature = Wx + b
接下来对特征计算 Softmax: 都计算一个 exp 函数,然后再进行标准化(让所有类别输出的概率值和为1)
Softmax(x) = normalize(exp(x))
y = Softmax(Wx + b)
4. 初始化
首先注册 session, 并创建一个 placeholder。 第二个参数代表 tensor 的 shape。
1 2
| sess = tf.InteractiveSession() x = tf.placeholder(tf.float32, [None, 784])
|
接下来给 weights 和 bias 创建 Variable 对象。其中 W 的 shape 是[784,10]。
1 2
| W = tf.Variable(tf.zeros([784,10])) b = tf.Variable(tf.zeros([10]))
|
5. 实现算法
tf.nn 包含了大量神经网络的组件, softmax 是 tf.nn下的一个函数。tf.matmul 为矩阵乘法。
1
| y = tf.nn.softmax(tf.matmul(x, W) + b)
|
6. 定义 loss 函数
我们需要定义一个 loss function 来描述模型的分类精度。
对于多分类问题,通常使用 cross-entropy 来作为 loss function。
H(y) = - y' * log(y)
其中, y' 是真实结果,y是预测结果
reduce_sum 为求和, reduce_mean 对每个 batch 数据求均值。
1 2 3
| yLabel = tf.placeholder(tf.float32, [None, 10]) cross_entropy = tf.reduce_mean(-tf.reduce_sum(yLabel * tf.log(y), reduction_indices=[1]))
|
7. 优化算法
我们采用常见的随机梯度下降,tensorflow 根据我们定义的整个计算图自动求导,并根据反向传播算法进行训练,在每一轮迭代时更新参数来减少 loss 。
1 2
| # 设置学习速率为0.5,优化目标设定为cross_entropy train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
|
8. 开始训练
随机取 100 个样本进行迭代训练。
1 2 3
| for i in range(1000): batch_xs, batch_ys = dataSet.train.next_batch(100) train_step.run({x: batch_xs, yLabel: batch_ys})
|
9. 查看准确率
tf.cast 将 bool 型转换为 float32。tf.argmax(y, 1)
是求各个预测的数字中概率最大的那一个。
1 2
| correctPred = tf.equal(tf.argmax(y, 1), tf.argmax(yLabel, 1)) accuracy = tf.reduce_mean(tf.cast(correctPred, tf.float32))
|
10. 测试数据
1
| print(accuracy.eval({x: dataSet.test.images, yLabel: dataSet.test.labels}))
|
11. 运行结果
准确率0.9162
即有 92%
的准确率
12. 其他
我们定义的各个公式其实只是 Computation Graph
,在执行这行代码时,计算还没有实际发生,只有等调用 run
方法,并 feed
数据时计算才真正执行。 比如 cross_entropy
、train_step
、accuracy
等都是计算图中的节点,而并不是数据结果,我们可以通过调用 run
方法执行这些节点或者说运算操作来调取结果。
13. 完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| # -*- coding: utf-8 -*- # !/usr/bin/env python from tensorflow.examples.tutorials.mnist import input_data import tensorflow as tf dataSet = input_data.read_data_sets("MNIST_data/", one_hot=True) # print(dataSet.train.images.shape,dataSet.train.labels.shape) # print(dataSet.test.images.shape,dataSet.test.labels.shape) # print(dataSet.validation.images.shape,dataSet.validation.labels.shape) 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) yLabel = tf.placeholder(tf.float32, [None, 10]) cross_entropy = tf.reduce_mean(-tf.reduce_sum(yLabel * tf.log(y), reduction_indices=[1])) # 设置学习速率为0.5,优化目标设定为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 = dataSet.train.next_batch(100) train_step.run({x: batch_xs, yLabel: batch_ys}) correctPred = tf.equal(tf.argmax(y, 1), tf.argmax(yLabel, 1)) accuracy = tf.reduce_mean(tf.cast(correctPred, tf.float32)) # 将测试数据输入到评测流程 print(accuracy.eval({x: dataSet.test.images, yLabel: dataSet.test.labels}))
|