tensorflow的学习心得(二)_MNIST代码详解

本文是讲关于tensorflow基于mnist的手写数字的识别代码详解,主要分为2个部分

参考链接:

https://www.youtube.com/watch?v=BhpvH5DuVu8&index=46&list=PLQVvvaa0QuDfKTOs3Keq_kaG2P55YRn5v

https://pythonprogramming.net/tensorflow-deep-neural-network-machine-learning-tutorial/

1. 程序中具体函数详细解释

首先我们先回顾上一篇的博文的函数和知识点,实现一个两个常量的乘法运算,但是中间包含了tensorflow最基本的操作:

  1. 构造模型
  2. 启动Session
  3. 带入值运算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import tensorflow as tf #导入tensorflow包
x1=tf.constant([5]) #对常量5进行声明
x2=tf.constant([6]) #对常量6进行声明
#在tensorflow中的两个常量进行相乘
result1 = tf.multiply(x1,x2)
sess=tf.Session() #创建一个session
#让tf在session中运行,表示tensor里面的值
print(sess.run(result1))
sess.close()
'''
#更快速的写法
with tf.Session() as sess:
print(sess.run(result1))
'''

那么最后的结果就是5X6=30,但是这个30是在tensor里面的,所以会显示成[30]

好,那么快速来说明这篇基础代码中所需要的函数和说明吧。

首先,我们需要了解一下我们整个代码的逻辑结构:

我们的目的是,使用我们现有的数据去训练我们的神经网络(training data去不断的feed我们的NN),然后,使用test data去测试我们这个NN的识别率是多少。
注:我们这里有三层hidden layer

如何训练自己的神经网络(转自知乎答案,简单形象又有趣的讲解神经网络):

最开始输入层输入特征向量,网络层层计算获得输出,输出层发现输出的正确的类号不一样,这时它就让最后一层神经元进行参数调整,最后一层神经元不仅自己调整参数,还会勒令它的倒数第二层神经元调整,层层往回退着调整(这就完成了一个epoch)。经过调整后的网络会在样本中继续测试,如果输出还是老分错,继续来一轮回退调整,直到网络输出满意为止。

那整体训练的过程就是:

1.首先取出我们的input data(batch_size个数据/1个iteration/第一次epoch的前半段)传递给hidden layer1。通过hidden layer1的W和b运算出了l1,得到:

1
l1=W1X + B1 #这里X是input的data
1
2
3
4
5
hidden_1_layer = {'weights': tf.Variable(tf.random_normal([784, n_nodes_hl1])),
'biases':tf.Variable(tf.random_normal([n_nodes_hl1]))}
l1 = tf.add(tf.matmul(data, hidden_1_layer['weights']),hidden_1_layer['biases'])
l1 = tf.nn.relu(l1)

把hidden layer1的输出值当成hidden layer2的输入值。之前要经过activation function(激活函数,这一个可以看看这块参考资料:https://www.zhihu.com/question/22334626)

2.以此类推,把hidden layer2 输出值(经过activation function后)当成hidden layer3的输入值,把hidden layer3的输出值(经过activation function后)当成output layer的输入值。

3.然后得到的结果与预期结果进行比较,得到一个loss function,然后使用optimaizer function(一般我们使用SGD)去最逐步减小我们的loss function(一般就是使用backpropagation算法,去一点一点得使得我们参数(hidden layer的weight和bias)接近我们的正确答案)。

这就是我们整体的一个训练过程,中间还有一些概念需要理解:

1.在backpropagation的时候,我们会有一个learning rate(学习率)的概念,它是一个loss function在调解我们的参数时快慢的一个影响因素:
学习率决定了权值的更新速度,设置太大会使权值越过最优值,太小会使下降速度过慢,算法长时间不能收敛。靠人为干预调整参数需要不断的调整学习率。

2.1个epoch的时间=feed+backpro的过程,不能设置太多,有时候会overfitting。

最后,在经历过所有的epoch之后,我们就可以拿我们的test data去测试整改神经网络的准确率了。

是不是很意外,很特么惊喜,说了这么多,我都等不及了,赶紧看看如何用代码实现吧。

1. import data:

1
2
3
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)

这一块就是导入我们所需要的dataset(数据包中就已经处理好了,可以直接用)

2. 声明模型中变量:

1
2
3
4
5
6
7
8
9
10
#各层模型的节点数,可以随意指定
n_nodes_hl1 = 500
n_nodes_hl2 = 500
n_nodes_hl3 = 500
n_classes = 10
batch_size = 100
x = tf.placeholder('float'[None,784])
y = tf.placeholder('float')
n_classes: 就是我们的标签数,有10个(0~9)所以是10个
batch_size: the number of samples for each batch

这是我网上找的关于batch_size的解释。

我的理解是:每次我们直接的进行神经网络的训练的时候,需要给我们的neural network 去feed很多数据量,那么这个batch_size就是指每次去feed这些数据量的大小。(每次训练在训练集中取batchsize个样本训练)

这里规定100,但是其实规定多少都是很有讲究的,大了的话,太耗时间,小了的话,训练速度更是缓慢。
如何选用合适的batch_size,更是以后调参的关键。

参考资料:
http://blog.csdn.net/ycheng_sjtu/article/details/49804041

这里顺便提一下其他几个词: epoch,iteration

epoch:

1个epoch相当于使用所有数据集(所有样本)去训练NN(neural net work,以下省略)一次。(1epoch=feed+backpro)

iteration:

1个iteration等于使用batchsize个样本训练一次(这里我是引用其他人的理解)

placeholder

上一篇文章我已经讲解了对于placeholder的理解和看法.

这里的placeholder的X指的是以后我们会填充的数据集(即一张一张的手写图片:dataset)

这里的Y值的就是这些数据集所对应的label(标签)

3. 定义NN结构:

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
def neural_network_model(data):
#input_data * weight + biases
hidden_1_layer = {'weights': tf.Variable(tf.random_normal([784, n_nodes_hl1])),
'biases':tf.Variable(tf.random_normal([n_nodes_hl1]))}
hidden_2_layer = {'weights': tf.Variable(tf.random_normal([n_nodes_hl1, n_nodes_hl2])),
'biases':tf.Variable(tf.random_normal([n_nodes_hl2]))}
hidden_3_layer = {'weights': tf.Variable(tf.random_normal([n_nodes_hl2, n_nodes_hl3])),
'biases':tf.Variable(tf.random_normal([n_nodes_hl3]))}
output_layer = {'weights': tf.Variable(tf.random_normal([n_nodes_hl3, n_classes])),
'biases':tf.Variable(tf.random_normal([n_classes]))}
l1 = tf.add(tf.matmul(data, hidden_1_layer['weights']),hidden_1_layer['biases'])
l1 = tf.nn.relu(l1)
l2 = tf.add(tf.matmul(l1, hidden_2_layer['weights']),hidden_2_layer['biases'])
l2 = tf.nn.relu(l2)
l3 = tf.add(tf.matmul(l2, hidden_3_layer['weights']),hidden_3_layer['biases'])
l3 = tf.nn.relu(l3)
output = tf.matmul(l3, output_layer['weights'])+output_layer['biases']
return output

这一段是设计我们的神经网络,也就是tensorflow中的第一步:构建flow graph,把NN中的结构和里面所需要的参数规划好(input data作为hidden layer1的输入,经过激活函数(这里用的是relu)后,hidden layer1的输出作为hidden layer2的输入…etc)。

4. 训练神经网络

我们已经实现了我们的基本网络结构,我们需要去设置我们的training process。

调用NN模型

那么首先,我们要在训练NN的函数中,调用我们之前已经声明好的NN

1
2
def train_neural_netword(x): #x是dataset
prediction = nural_network_model(x)

然后我们会产生一个预测值,是根据数据的经过我们的neural_network_model函数后,得到的一个output值。
那么,我们可以看到我们的输出,是one hot array,就是[0,0,0,1,0,0,0,0,0,0](如果答案是3)。

损失函数

现在我们去创造一个损失的变量,是测量我们与实际值差了多少。

cost=tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits(logits =prediction,labels =y) )

这里要强调一下

tf.nn.softmax_cross_entropy_with_logits
这里强调一下这个函数的作用。

tf.nn.softmax_cross_entropy_with_logits computes the cross entropy of the result after applying the softmax function (but it does it all together in a more mathematically careful way). It’s similar to the result of:

sm = tf.nn.softmax(x)

ce = cross_entropy(sm)

or:
It is only used during training. The logits are the unnormalized log probabilities output the model (the values output before the softmax normalization is applied to them).

官网解释:
Computes softmax cross entropy between logits and labels.

Measures the probability error in discrete classification tasks in which the classes are mutually exclusive (each entry is in exactly one class).

参考资料:
https://stackoverflow.com/questions/34240703/difference-between-tensorflow-tf-nn-softmax-and-tf-nn-softmax-cross-entropy-with

https://www.tensorflow.org/api_docs/python/tf/nn/softmax_cross_entropy_with_logits


然后这个变量会通过不断的操作weight去不断的变小。

利用AdamOptimizer函数去缩小损失函数。(比较常用的函数之一,类似于SGD或mini-batch GD,AdaGrad等等)

1
2
3
cost=tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits(logits =prediction,labels =y) )
optimizer=tf.train.AdamOptimizer().minimize(cost)

在AdamOptimizer函数中,可以设定我们的学习率,这里我们使用默认的0.001

启动Session

设置好我们的参数以后,我们需要启动Session并设置我们的epoch数(1个epoch=feed+backpropagation)

1
2
3
hm_epochs = 10
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())

在session中,所有变量要初始化才能使用(上一篇博客详细说明过)

主要训练过程
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
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
for epoch in range(hm_epochs):
epoch_loss = 0
#这里有多少个数据,然后除以batch的数量,得到每一次epoch中多少批循环(每一批有batch个数的data)
for _ in range(int(mnist.train.num_examples/batch_size)):
#这里是已经处理好的x和y数据和label,我们在自己数据中需要了解如何使用
epoch_x, epoch_y=mnist.train.next_batch(batch_size)
#这里是实现损失函数优化的动作,把数据x和label(y)填充进去
_, c=sess.run([optimizer, cost], feed_dict = {x: epoch_x, y: epoch_y})
epoch_loss += c
#输出现在是第几个epoch,然后现在的损失函数是多少
print('Epoch', epoch, 'completed out of', hm_epochs,'loss:',epoch_loss)
#上面是训练整个神经网络,训练结束后(for结束后)。
#经过优化后得到的weight,我们进去下面一个部分。
#这里是比较我们的预测结果和原设y是否一样(equal函数返回一个boolean类型值)
correct = tf.equal(tf.argmax(prediction,1), tf.argmax(y,1))
#这里会告诉我们有大约多少的预测率
accuracy = tf.reduce_mean(tf.cast(correct,'float'))
#evaluate整个x与y的准确率
print('Accuracy:',accuracy.eval({x:mnist.test.images, y:mnist.test.labels}))

这是整篇过程中最主要的代码段,下面我们来进行下详细的解释。


首先解释一下python中for _ 的用法:

1
2
3
for _ in range (5):
print _
#输出为 1 2 3 4 5

那么在python中对于无需关注其实际含义的变量可以用来代替。
(这次for 循环结束后,
就不用管了,我们只要这个循环的过程)


对于每一个epoch来说,我们需要把batch个数目的data放入NN中,然后去优化还有调成weight去减少cost。
设置第一个for做epoch循环.

第二个for做一个epoch中batch_size个data的处理:

每一次for调用一次,调用cost和optimizer去改变weight的值。<br>
评估当前在第几个epoch中,损失量是多少。

在我们训练完weight之后,得到的output要把一开始的label(y)进行比较,确定是否正确,然后再计算准确率。

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import tensorflow as tf
'''
input data > weight> hidden layer 1 (activation function )> weights > hidden l2
(activation function)>weights>output layer
compare output to intended output> loss function(cross entropy)
optimization function(optimizer)>minimize cost(adamOptimizer ....SGD, AdaGrad)
backpropagation
feed forward + backprop = epoch
'''
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)
#10 classes, 0-9
n_nodes_hl1=500
n_nodes_hl2=500
n_nodes_hl3=500
n_classes = 10
batch_size= 100
#x is the data, y is the labe of that data
x = tf.placeholder('float', [None, 784])
y = tf.placeholder('float')
def neural_network_model(data):
#input_data * weight + biases
hidden_1_layer = {'weights': tf.Variable(tf.random_normal([784, n_nodes_hl1])),
'biases':tf.Variable(tf.random_normal([n_nodes_hl1]))}
hidden_2_layer = {'weights': tf.Variable(tf.random_normal([n_nodes_hl1, n_nodes_hl2])),
'biases':tf.Variable(tf.random_normal([n_nodes_hl2]))}
hidden_3_layer = {'weights': tf.Variable(tf.random_normal([n_nodes_hl2, n_nodes_hl3])),
'biases':tf.Variable(tf.random_normal([n_nodes_hl3]))}
output_layer = {'weights': tf.Variable(tf.random_normal([n_nodes_hl3, n_classes])),
'biases':tf.Variable(tf.random_normal([n_classes]))}
l1 = tf.add(tf.matmul(data, hidden_1_layer['weights']),hidden_1_layer['biases'])
l1v = tf.nn.relu(l1)
l2 = tf.add(tf.matmul(l1, hidden_2_layer['weights']),hidden_2_layer['biases'])
l2 = tf.nn.relu(l2)
l3 = tf.add(tf.matmul(l2, hidden_3_layer['weights']),hidden_3_layer['biases'])
l3 = tf.nn.relu(l3)
output = tf.matmul(l3, output_layer['weights'])+output_layer['biases']
return output
def train_neural_network(x):
prediction = neural_network_model(x)
print ( prediction)
cost = tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits(logits =prediction,labels =y) )
optimizer = tf.train.AdamOptimizer().minimize(cost)
hm_epochs = 10
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
for epoch in range(hm_epochs):
epoch_loss = 0
#这里有多少个数据,然后除以batch的数量,得到每一次epoch中多少批循环(每一批有batch个数的data)
for _ in range(int(mnist.train.num_examples/batch_size)):
#这里是已经处理好的x和y数据和label,我们在自己数据中需要了解如何使用
epoch_x, epoch_y=mnist.train.next_batch(batch_size)
#这里是实现损失函数优化的动作,把数据x和label(y)填充进去
_, c=sess.run([optimizer, cost], feed_dict = {x: epoch_x, y: epoch_y})
epoch_loss += c
#输出现在是第几个epoch,然后现在的损失函数是多少
print('Epoch', epoch, 'completed out of', hm_epochs,'loss:',epoch_loss)
#上面是训练整个神经网络,训练结束后(for结束后)。
#经过优化后得到的weight,我们进去下面一个部分。
#这里是比较我们的预测结果和原设y是否一样(equal函数返回一个boolean类型值)
correct = tf.equal(tf.argmax(prediction,1), tf.argmax(y,1))
#这里会告诉我们有大约多少的预测率
accuracy = tf.reduce_mean(tf.cast(correct,'float'))
#evaluate整个x与y的准确率
print('Accuracy:',accuracy.eval({x:mnist.test.images, y:mnist.test.labels}))
train_neural_network(x)
坚持原创技术分享,您的支持将鼓励我继续创作!