1. 程式人生 > >tensorflow安裝、流程,概念和簡單程式碼註釋

tensorflow安裝、流程,概念和簡單程式碼註釋

1.tensorflow的執行流程

tensorflow的執行流程主要有2步,分別是構造模型訓練

在構造模型階段,我們需要構建一個圖(Graph)來描述我們的模型。所謂圖,也可以理解為流程圖,就是將資料的輸入->中間處理->輸出的過程表示出來,就像下面這樣。

 20160601101108139.png-26.2kB

注意此時是不會發生實際運算的。而在模型構建完畢以後,會進入訓練步驟。此時才會有實際的資料輸入,梯度計算等操作。那麼,如何構建抽象的模型呢?這裡就要提到tensorflow中的幾個概念:Tensor,Variable,placeholder,而在訓練階段,則需要介紹Session。下面先解釋一些上面的幾個概念

1.1概念描述

tensor: tensor 資料結構來代表所有的資料

constant:常量 c = tf.constant(0.1,shape=[2,2]) 

Variable: 變數 v = tf.Variable(initial)  initial為一個初始化的值

placeholder:佔位符 x = tf.placeholder(tf.float32,[1, 5],name='input')

Session:會話

1.1.1 Tensor

Tensor的意思是張量,tensorflow中所有資料都是用tensor表示的,tensor有不同的型別,比如constant variable zeros等等

import tensorflow as tf# 在下面所有程式碼中,都去掉了這一行,預設已經匯入

a = tf.zeros(shape=[1,2])

不過要注意,因為在訓練開始前,所有的資料都是抽象的概念,也就是說,此時a只是表示這應該是個1*5的零矩陣,而沒有實際賦值,也沒有分配空間,所以如果此時print,就會出現如下情況:

print(a)

#===>Tensor("zeros:0", shape=(1, 2), dtype=float32)

只有在訓練過程開始後,才能獲得a的實際值

sess = tf.InteractiveSession()

print(sess.run(a))

#===>[[ 0.  0.]]

這邊設計到Session概念,後面會提到

1.1.2 Variable

故名思議,是變數的意思。一般用來表示圖中的各計算引數,包括矩陣,向量等。例如,我要表示上圖中的模型,那表示式就是 

y=Relu(Wx+b)


(relu是一種啟用函式,具體可見這裡)這裡W和b是我要用來訓練的引數,那麼此時這兩個值就可以用Variable來表示。Variable的初始函式有很多其他選項,這裡先不提,只輸入一個Tensor也是可以的

W = tf.Variable(tf.zeros(shape=[1,2]))

注意,此時W一樣是一個抽象的概念,而且與Tensor不同,Variable必須初始化以後才有具體的值

tensor = tf.zeros(shape=[1,2])

variable = tf.Variable(tensor)

sess = tf.InteractiveSession()

# print(sess.run(variable))  # 會報錯

sess.run(tf.initialize_all_variables())

# 對variable進行初始化print(sess.run(variable))

#===>[[ 0.  0.]]

1.1.3 placeholder

又叫佔位符,同樣是一個抽象的概念。用於表示輸入輸出資料的格式。告訴系統:這裡有一個值/向量/矩陣,現在我沒法給你具體數值,不過我正式執行的時候會補上的!例如上式中的x和y。因為沒有具體數值,所以只要指定尺寸即可

x = tf.placeholder(tf.float32,[1, 5],name='input')

y = tf.placeholder(tf.float32,[None, 5],name='input')

上面有兩種形式,第一種x,表示輸入是一個[1,5]的橫向量。 
而第二種形式,表示輸入是一個[?,5]的矩陣。那麼什麼情況下會這麼用呢?就是需要輸入一批[1,5]的資料的時候。比如我有一批共10個數據,那我可以表示成[10,5]的矩陣。如果是一批5個,那就是[5,5]的矩陣。tensorflow會自動進行批處理

1.1.4 Session

session,也就是會話。我的理解是,session是抽象模型的實現者。為什麼之前的程式碼多處要用到session?因為模型是抽象的嘛,只有實現了模型以後,才能夠得到具體的值。同樣,具體的引數訓練,預測,甚至變數的實際值查詢,都要用到session,看後面就知道了

1.2 模型構建

這裡我們使用官方tutorial中的mnist資料集的分類程式碼,公式可以寫作 

z=Wx+ba=softmax(z)
那麼該模型的程式碼描述為

# 建立抽象模型x = tf.placeholder(tf.float32, [None, 784]) #輸入佔位符y = tf.placeholder(tf.float32, [None, 10])  #輸出佔位符(預期輸出)

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

b = tf.Variable(tf.zeros([10]))

a = tf.nn.softmax(tf.matmul(x, W) + b)      # a表示模型的實際輸出

# 定義損失函式和訓練方法

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y * tf.log(a), reduction_indices=[1])) #損失函式為交叉熵

optimizer = tf.train.GradientDescentOptimizer(0.5) #梯度下降法,學習速率為0.5

train = optimizer.minimize(cross_entropy)  # 訓練目標:最小化損失函式

可以看到這樣以來,模型中的所有元素(圖結構,損失函式,下降方法和訓練目標)都已經包括在train裡面。我們可以把train叫做訓練模型。那麼我們還需要測試模型

correct_prediction = tf.equal(tf.argmax(a, 1), tf.argmax(y, 1))

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

上述兩行程式碼,tf.argmax表示找到最大值的位置(也就是預測的分類和實際的分類),然後看看他們是否一致,是就返回true,不是就返回false,這樣得到一個boolean陣列。tf.cast將boolean陣列轉成int陣列,最後求平均值,得到分類的準確率(怎麼樣,是不是很巧妙)

1.3 實際訓練

有了訓練模型和測試模型以後,我們就可以開始進行實際的訓練了

sess = tf.InteractiveSession()      # 建立互動式會話

tf.initialize_all_variables().run() # 所有變數初始化

for i in range(1000):

    batch_xs, batch_ys = mnist.train.next_batch(100)    #獲得一批100個數據

    train.run({x: batch_xs, y: batch_ys})   #給訓練模型提供輸入和輸出

print(sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels}))

可以看到,在模型搭建完以後,我們只要為模型提供輸入和輸出,模型就能夠自己進行訓練和測試了。中間的求導,求梯度,反向傳播等等繁雜的事情,tensorflow都會幫你自動完成。

2. 實際程式碼

實際操作中,還包括了獲取資料的程式碼

"""A very simple MNIST classifier.

See extensive documentation at

http://tensorflow.org/tutorials/mnist/beginners/index.md

"""from __future__ import absolute_importfrom __future__ import divisionfrom __future__ import print_function

# Import data

from tensorflow.examples.tutorials.mnist import input_data

import tensorflow as tf

flags = tf.app.flags

FLAGS = flags.FLAGS

flags.DEFINE_string('data_dir', '/tmp/data/', 'Directory for storing data')# 把資料放在/tmp/data資料夾中

mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)   #讀取資料集

# 建立抽象模型

x = tf.placeholder(tf.float32, [None, 784])# 佔位符

y = tf.placeholder(tf.float32, [None, 10])

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

b = tf.Variable(tf.zeros([10]))

a = tf.nn.softmax(tf.matmul(x, W) + b)

# 定義損失函式和訓練方法

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y * tf.log(a), reduction_indices=[1]))  #損失函式為交叉熵

optimizer = tf.train.GradientDescentOptimizer(0.5) #梯度下降法,學習速率為0.5

train = optimizer.minimize(cross_entropy) # 訓練目標:最小化損失函式

# Test trained model

correct_prediction = tf.equal(tf.argmax(a, 1), tf.argmax(y, 1))

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

# Train

sess = tf.InteractiveSession()      # 建立互動式會話

tf.initialize_all_variables().run()

for i in range(1000):

    batch_xs, batch_ys = mnist.train.next_batch(100)

    train.run({x: batch_xs, y: batch_ys})

print(sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels}))

得到的分類準確率在91%左右