1. 手写数字数据集
1.1. 下载数据集
下载地址:http://yann.lecun.com/exdb/mnist/
下载这4个数据集,放到工程的 ./data/mnist/input_data/ 目录下,后面程序中要读取这些数据1
2
3
4train-images-idx3-ubyte.gz: 训练集图片
train-labels-idx1-ubyte.gz: 训练集标签
t10k-images-idx3-ubyte.gz: 测试集图片
t10k-labels-idx1-ubyte.gz: 测试集标签
TensorFlow也提供了相应下载并读取MNIST数据集的API
1 | from tensorflow.examples.tutorials.mnist import input_data |
1.2. 查看数据集
文件是二进制格式的,具体数据格式在下载的地方有说明。TensorFlow已经提供了读取数据的API,直接用即可1
2from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./data/mnist/input_data/", one_hot=True)
mnist.train.images就是训练集图片。有55000张图片,即55000个样本。每张图片都是灰度图,共28x28=784个像素,每个像素点的灰度值是浮点数,范围在[0,1]之间,0代表黑色,1代表白色,介于0和1之间就是灰色。你可以将[0,1]*255==>[0,255],放大到256进制,就可以理解了。数据中,784个像素的数据都放在一行。
1 | mnist.train.images.shape |
mnist.train.labels是训练集标签。经过one-hot编码,每一个样本是10个元素的数组,只有一个元素的值是1,其它值都为0。值为1对应的下标就是该图片代表的数字,数字范围是[0,9]1
2
3
4
5
6
7
8
9
10
11
12
13
14mnist.train.labels.shape
(55000, 10)
mnist.train.labels
array([[0., 0., 0., ..., 1., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 1., 0.]])
mnist.train.labels[0]
array([0., 0., 0., 0., 0., 0., 0., 1., 0., 0.]) # 代表数字7
测试集有10000个样本1
2
3
4mnist.test.images.shape
(10000, 784)
mnist.test.labels.shape
(10000, 10)
1.3. mnist.train.next_batch 批量迭代获取训练数据集
1 | x, y = mnist.train.next_batch(1) |
2. 单一隐藏层神经网络实现手写数字图片识别
单一隐藏层神经网络就是全连接神经网络。单一隐藏层,就是只有全连接层。
1 | import os |
2.1. 添加可视化
添加以下内容
1 | # 要显示的标题信息 |
启动tensorboard1
tensorboard --logdir summary/test
2.2. 添加模型保存以及结果预测
添加以下内容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# 设置命令行参数is_train,1代表进行训练,0代表进行结果测试
tf.app.flags.DEFINE_integer("is_train", 1, "指定程序是预测还是训练")
# 获取命令行参数
FLAGS = tf.app.flags.FLAGS
def full_connected():
# 创建一个saver
saver = tf.train.Saver()
with tf.Session() as sess:
if FLAGS.is_train == 1:
for i in range(2000):
# ....
# 保存模型
saver.save(sess, "./model/fc_model")
else:
# 加载模型
saver.restore(sess, "./model/fc_model")
# 如果是0,做出预测
for i in range(100):
# 每次测试一张图片,y_test数据格式为[0,0,0,0,0,1,0,0,0,0]
x_test, y_test = mnist.test.next_batch(1)
# 求出测试标签对应的数字
digit_true = tf.argmax(y_test, 1).eval()
# 求出预测标签对应的数字
digit_test = tf.argmax(sess.run(y_predict, feed_dict={x: x_test, y_true: y_test}), 1).eval()
print("第%d张图片,手写数字图片目标是:%d, 预测结果是:%d %s" % (
i,
digit_true,
digit_test,
"" if digit_true == digit_test else "错误"
))
先训练得到模型并保存,再加载模型进行测试1
2python mnist.py --is_train=1 # 训练
python mnist.py --is_train=0 # 测试
2.3. 最终代码
1 | import os |
3. 卷积神经网络实现手写数字图片识别
1 | import os |
3.1. 步长
步长一般设置为1,这样观察得更仔细些
3.2. 激活层
为什么要激活函数?如果没有激活函数,神经网络只能解决线性问题,反之有了激活函数,就能解决非线性问题
为什么不用sigmoid,而是relu?
- 从计算公式可以看出,sigmoid比relu计算量大
- sigmoid容易导致梯度爆炸