TensorFlow tutorial mnist beginners

从示例开始

导入

1
2
import tensorflow as tf
import numpy as np # 和tf配合使用
D:\Anaconda3\Anaconda3_py36\lib\site-packages\h5py\__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters

构造线性模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# generate phony data | 生成假数据
# 实际应用应该是面对真实的数据
# 100个点,(2x100)
x_data = np.float32(np.random.rand(2, 100))
y_data = np.dot([0.100, 0.200], x_data)+0.300

# 构造线性模型
b = tf.Variable(tf.zeros([1])) # tensor of shape 1
W = tf.Variable(tf.random_uniform([1, 2], minval=-0.1, maxval=1.0)) # tensor of shape 1x2 whose values are from a uniform distribution
# in the range of [minval, maxval)
y = tf.matmul(W, x_data)+b

# 最小化方差
loss = tf.reduce_mean(tf.square(y-y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)
1
2
3
# 初始化变量
# init = tf.initialize_all_variables()
init = tf.global_variables_initializer()
1
2
3
# 启动计算图(graph)
sess = tf.Session() # 创建会话
sess.run(init)
1
2
3
4
5
# 拟合平面
for step in range(0, 201):
sess.run(train)
if step%20==0:
print("Step: ", step, " W= ",sess.run(W), " b= ", sess.run(b))
Step:  0  W=  [[0.4871506  0.41139394]]  b=  [-0.09778017]
Step:  20  W=  [[0.22539519 0.34252512]]  b=  [0.15573283]
Step:  40  W=  [[0.14763923 0.26675704]]  b=  [0.23892412]
Step:  60  W=  [[0.11975352 0.22945689]]  b=  [0.2737922]
Step:  80  W=  [[0.10842387 0.21279107]]  b=  [0.2887098]
Step:  100  W=  [[0.10362242 0.20552918]]  b=  [0.2951307]
Step:  120  W=  [[0.10156146 0.20238699]]  b=  [0.29789925]
Step:  140  W=  [[0.10067356 0.2010301 ]]  b=  [0.2990936]
Step:  160  W=  [[0.10029061 0.20044449]]  b=  [0.29960892]
Step:  180  W=  [[0.10012538 0.20019177]]  b=  [0.29983127]
Step:  200  W=  [[0.10005409 0.20008272]]  b=  [0.2999272]
1
2
# 关闭会话
sess.close()

MNIST机器学习入门

1
2
3
4
# http://yann.lecun.com/exdb/mnist/  to download mnist dataset
# https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/mnist/input_data.py
# to read dataset
from load_mnist import *
1
2
3
import tensorflow.examples.tutorials.mnist.input_data as input_data
minst_dir = "MNIST_data/"
mnist = input_data.read_data_sets(minst_dir, one_hot=True)
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
WARNING:tensorflow:From D:\Anaconda3\Anaconda3_py36\lib\site-packages\tensorflow\contrib\learn\python\learn\datasets\mnist.py:290: DataSet.__init__ (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.
Instructions for updating:
Please use alternatives such as official/mnist/dataset.py from tensorflow/models.

下载下来的数据集被分成两部分:60000行的训练数据集(mnist.train)和10000行的测试数据集(mnist.test).

每一个MNIST数据单元有两部分组成:一张包含手写数字的图片和一个对应的标签。我们把这些图片设为“xs”,把这些标签设为“ys”。训练数据集和测试数据集都包含xs和ys,比如训练数据集的图片是 mnist.train.images ,训练数据集的标签是 mnist.train.labels.

每一张图片包含28像素X28像素。我们可以用一个数字数组来表示这张图片:

我们把这个数组展开成一个向量,长度是 28x28 = 784。如何展开这个数组(数字间的顺序)不重要,只要保持各个图片采用相同的方式展开。从这个角度来看,MNIST数据集的图片就是在784维向量空间里面的点, 并且拥有比较复杂的结构 (提醒: 此类数据的可视化是计算密集型的)。

在MNIST训练数据集中,mnist.train.images 是一个形状为 [60000, 784]的张量,第一个维度数字用来索引图片,第二个维度数字用来索引每张图片中的像素点。在此张量里的每一个元素,都表示某张图片里的某个像素的强度值,值介于0和1之间。

相对应的MNIST数据集的标签是介于0到9的数字,用来描述给定图片里表示的数字。为了用于这个教程,我们使标签数据是”one-hot vectors”。 一个one-hot向量除了某一位的数字是1以外其余各维度数字都是0。所以在此教程中,数字n将表示成一个只有在第n维度(从0开始)数字为1的10维向量。比如,标签0将表示成([1,0,0,0,0,0,0,0,0,0,0])。因此, mnist.train.labels 是一个[60000, 10]的数字矩阵。

1
2
3
4
5
6
7
# x represent the input
# None means number of images is adaptable
# a 28x28 image is flatten to a vector of 784
x = tf.placeholder("float", [None, 784])

W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

Softmax regression

关于Softmax可以阅读这篇或者这篇.

整个回归模型:

1
2
# softmax
y = tf.nn.softmax(tf.matmul(x, W)+b)

训练模型

使用交叉熵损失函数,更多介绍看这篇.

1
2
3
4
y_ = tf.placeholder("float", [None, 10])

# 注意,这里的交叉熵不仅仅用来衡量单一的一对预测和真实值,而是所有100幅图片的交叉熵的总和
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
1
2
# gradient descent and backprapagation
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

更多优化算法点击这里.

1
2
# init graph
init = tf.global_variables_initializer()
1
2
3
4
5
6
with tf.Session() as sess:
sess.run(init)
for step in range(1001):
batch_xs, batch_ys = mnist.train.next_batch(100)
feed_dict ={x: batch_xs, y_:batch_ys}
sess.run(train_step, feed_dict)

评估我们的模型

tf.argmax 是一个非常有用的函数,它能给出某个tensor对象在某一维上的其数据最大值所在的索引值。由于标签向量是由0,1组成,因此最大值1所在的索引位置就是类别标签,比如tf.argmax(y,1)返回的是模型对于任一输入x预测到的标签值,而 tf.argmax(y_,1) 代表正确的标签,我们可以用 tf.equal 来检测我们的预测是否真实标签匹配(索引位置一样表示匹配)。

1
2
3
4
5
6
7
8
9
10
with tf.Session() as sess:
sess.run(init)
for step in range(1001):
batch_xs, batch_ys = mnist.train.next_batch(100)
feed_dict ={x: batch_xs, y_:batch_ys}
sess.run(train_step, feed_dict)
if step%100==0:
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print(step, " train acc: ", sess.run(accuracy, feed_dict))
0  train acc:  0.48
100  train acc:  0.94
200  train acc:  0.96
300  train acc:  0.93
400  train acc:  0.93
500  train acc:  0.89
600  train acc:  0.96
700  train acc:  0.94
800  train acc:  0.94
900  train acc:  0.95
1000  train acc:  0.98
1
2
3
4
5
6
7
8
9
10
11
12
13
14
with tf.Session() as sess:
sess.run(init)
for step in range(1001):
batch_xs, batch_ys = mnist.train.next_batch(100)
feed_dict ={x: batch_xs, y_:batch_ys}
sess.run(train_step, feed_dict)
# if step%100==0:
# correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
# accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
# print(step, " train acc: ", sess.run(accuracy, feed_dict))
# # for test set
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print("Test acc:", sess.run(accuracy, feed_dict={x:mnist.test.images, y_:mnist.test.labels}))
Test acc: 0.9138

更多内容https://www.tensorflow.org/tutorials/

总结

本文首先通过一个完整的线性回归的例子,展示了TensorFlow的基本使用,首先构造计算图graph,其中包含诸如Variableplaceholder等节点,以及节点之间的数学运算如矩阵乘法;接着对计算图初始化,tf.global_variables_initializer(),其中TensorFlow中很重要的就是回话session机制,通过会话来运行计算图;随后,通过会话进行训练,拟合并德大检测结果。

其次,使用TensorFlow完成了基于MNIST数据集,进行手写体识别的任务,并在测试集上实现了91%的正确率。
其完整过程,首先是准备数据,下载的数据被分为训练数据和测试数据。每种数据的基本单元都包含两部分,一部分是手写体图片,统一规格28x28,另一部分是对应的标记,来指出对应的数字,将原始图片展开向量表示,标记采用one-hot表示;
接着,构建softmax回归模型。使用梯度下降算法进行反向传播,最小化交叉熵损失进行训练。
最后,在测试机上测试,得到实验正确率指标,可以达到91%以上。