1. 概述
TensorFlow是Google開發的一款用於深度學習的python庫,TensorFlow用圖來表示計算任務,數據在創建的數據流圖中被處理。節點(operation,op)在圖中表示數學操作,圖中的線表示節點間相互聯系的多維數據數組,即張量(tensor)。訓練模型的過程中 tensor 會在幾點之間傳遞,由此也可以更好的理解TensorFlow這個名字。圖必須在會話里被啟動,會話(Session)將圖的 op 分發到CPU或GPU之類的計算設備上,同時執行op的方法,計算過后將產生的 tensor 返回。
張量(Tensor): * 張量有多種. 零階張量為 純量或標量 (scalar) 也就是一個數值. 比如
[1]
* 一階張量為 向量 (vector), 比如 一維的[1, 2, 3]
* 二階張量為 矩陣 (matrix), 比如 二維的[[1, 2, 3],[4, 5, 6],[7, 8, 9]]
* 以此類推, 還有 三階 三維的 ...
2. 基本用法
環境:python3.7 tensorflow1.15
使用一個簡單擬合二維線性函數的例子來解釋TensorFlow的基本用法,這樣更容易理解和記憶。整體代碼如下:
import tensorflow as tf import numpy as np # 針對線性方程 y = 0.1*x + 0.3,生成100個數據 x_data = np.random.rand(100).astype(np.float32) y_data = x_data*0.1 + 0.3 #構建一個線性模型 Weights = tf.Variable(tf.random_uniform([1],-1.0,1.0)) biases = tf.Variable(tf.zeros([1])) y = Weights*x_data + biases # 最小化方差 loss = tf.reduce_mean(tf.square(y-y_data)) optimizer = tf.train.GradientDescentOptimizer(0.5) train = optimizer.minimize(loss) # 初始化變量 init = tf.initialize_all_variables() # 啟動圖 sess = tf.Session() sess.run(init) # 擬合線性方程 for step in range(201): sess.run(train) if step%20 == 0: print(step,sess.run(Weights),sess.run(biases))
首先需要構建我們的數據集,生成隨機數據時使用numpy這個庫比較方便,然后就是構建一個線性模型, tf.Variable用來在模型構建過程中定義一個變量,這里定義一個權重 Weights,可以理解為y = a*x + b 中的參數 a,還定義了一個偏量 biases,可以理解為參數 b。定義完變量之后需要計算方差,並且使用優化器 tf.train.GradientDescentOptimizer(0.5)將方差降低至最小,使得預測數據和樣本數據盡量擬合。然后就是初始化變量,通過會話來啟動計算模型,最后訓練201回合,並每20回合輸出一次參數。下面我們從構件圖、會話、變量、傳入值、添加層、構建神經網絡等部分講解TensorFlow的使用。
2.1 構建圖
使用兩個矩陣相乘這個簡單的例子來解釋怎樣構建一個圖:
import tensorflow as tf # 創建一個 常量 op, 返回值 'matrix1' 代表這個 1x2 矩陣. matrix1 = tf.constant([[3., 3.]]) # 創建另外一個 常量 op, 返回值 'matrix2' 代表這個 2x1 矩陣. matrix2 = tf.constant([[2.]
,[2.]]) # 創建一個矩陣乘法 matmul op , 把 'matrix1' 和 'matrix2' 作為輸入. # 返回值 'product' 代表矩陣乘法的結果. product = tf.matmul(matrix1, matrix2)
圖中有三個節點,兩個矩陣常量使用 tf.constant()來定義,最后矩陣相乘得出結果,用tf.matmul(matrix1,matrix2)計算兩個矩陣相乘,並返回計算結果。這里只是定義了矩陣如何計算並沒有執行,計算的過程必須在會話中啟動,這部分在之后的會話中講解。
2.2 會話控制Session
Session是 Tensorflow 為了控制和輸出文件的執行的語句. 運行 session.run()
可以獲得你要得知的運算結果, 或者是你所要運算的部分。之前在矩陣相乘的例子中已經構建好了變量和常量,但是定義的計算方法並不是實際的運算過程,真正的運算過程要是用Session來激活product,並得到計算結果,使用會話控制Session的方法有兩種:
# method 1 sess = tf.Session() result = sess.run(product) print(result) sess.close() # [[12]] # method 2 with tf.Session() as sess: result2 = sess.run(product) print(result2) # [[12]]
2.3 變量Variable
和python的變量不同,TensorFlow中變量需要進行提前定義才能使用。
定義語法:state = tf.Variable()
變量定義過后還需要對其進行初始化,這一步尤為關鍵,很容易被忽略。
init = tf.initialize_all_variables()
到這一步變量還是沒有被激活,需要使用sess.run()來激活變量,TensorFlow中變量的使用必須要有定義、初始化、激活三個步驟之后才會在計算中被使用。下面是一個簡單的計數器:
# -創建一個變量, 初始化為標量 0. 初始化定義初值 state = tf.Variable(0, name="counter") # 創建一個 op, 其作用是使 state 增加 1 one = tf.constant(1) new_value = tf.add(state, one) update = tf.assign(state, new_value) # 啟動圖后, 變量必須先經過`初始化` (init) op 初始化, # 才真正通過Tensorflow的initialize_all_variables對這些變量賦初值 init_op = tf.initialize_all_variables() # 啟動默認圖, 運行 op with tf.Session() as sess: # 運行 'init' op sess.run(init_op) # 打印 'state' 的初始值 # 取回操作的輸出內容, 可以在使用 Session 對象的 run() 調用 執行圖時, # 傳入一些 tensor, 這些 tensor 會幫助你取回結果. # 此處只取回了單個節點 state, # 也可以在運行一次 op 時一起取回多個 tensor: # result = sess.run([mul, intermed]) print sess.run(state) # 運行 op, 更新 'state', 並打印 'state' for _ in range(3): sess.run(update) print sess.run(state) # 輸出: # 0 # 1 # 2 # 3
2.4傳入值 placeholder
placeholder是TensorFlow中的占位符,暫時存儲變量,TensorFlow如果想要從外部傳入data,那就需要使用 tf.placeholder(),然后以這種形式傳輸數據 sess.run(***,feed_dict={inputt:***}),下面代碼是一個簡單例子,傳值的工作交給了sess.run(),需要傳入的值放在了feed_dict={},並一一對應的每一個input。placeholder和feed_dict={}是綁定在一起出現的。
import tensorflow as tf #在 Tensorflow 中需要定義 placeholder 的 type ,一般為 float32 形式 input1 = tf.placeholder(tf.float32) input2 = tf.placeholder(tf.float32) # mul = multiply 是將input1和input2 做乘法運算,並輸出為 output ouput = tf.multiply(input1, input2) with tf.Session() as sess: print(sess.run(ouput, feed_dict={input1: [7.], input2: [2.]})) # [ 14.]
2.5 添加層 def add_layer()
最基本的神經網絡結構也包含輸入層、隱藏層、輸出層,在構建神經網絡過程中我們需要構建一層又一層的神經元,神經層中常見的參數包含weights、biases和激勵函數。
import tensorflow as tf def add_layer(inputs,in_size,out_size,activation_function=None): Weights = tf.Variable(tf.random_normal([in_size,out_size])) biases = tf.Variable(tf.zeros([1,out_size]) + 0.1) Wx_plus_b = tf.matmul(inputs,Weights) + biases if activation_function is None: outputs = Wx_plus_b else: outputs = activation_function(Wx_plus_b) return outputs
上面代碼是一個添加神經層的函數,參數包括該層輸入數據:inputs,輸入數據的大小:in_size、輸出數據的大小:out_size、激活函數:activation_function,默認的激活函數為None。
首先是定義參數weights和biases。因為在生成初始參數時,隨機變量(normal distribution)會比全部為0要好很多,所以我們這里的weights
為一個in_size
行, out_size
列的隨機變量矩陣。
Weights = tf.Variable(tf.random_normal([in_size, out_size]))
在機器學習中,biases
的推薦值不為0,所以我們這里是在0向量的基礎上又加了0.1
。
biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
下面,我們定義Wx_plus_b
, 即神經網絡未激活的值。其中,tf.matmul()
是矩陣的乘法。
Wx_plus_b = tf.matmul(inputs, Weights) + biases
當activation_function
——激勵函數為None
時,輸出就是當前的預測值——Wx_plus_b
,不為None
時,就把Wx_plus_b
傳到activation_function()
函數中得到輸出。
if activation_function is None: outputs = Wx_plus_b else: outputs = activation_function(Wx_plus_b)
最后,返回輸出,添加一個神經層的函數——def add_layer()
就定義好了。
return outputs
2.6 構建神經網絡
在之前的基礎上我們可以知道構建魔性的過程可以概括為:建圖——啟動圖——運行取值。
1、建圖
構建神經層想必是建圖的核心部分,之前我們已經構造好了add_layer()函數,通過輸入不同的參數我們可以構建不同的神經層。
def add_layer(inputs,in_size,out_size,activation_function=None): Weights = tf.Variable(tf.random_normal([in_size,out_size])) biases = tf.Variable(tf.zeros([1,out_size]) + 0.1) Wx_plus_b = tf.matmul(inputs,Weights) + biases if activation_function is None: outputs = Wx_plus_b else: outputs = activation_function(Wx_plus_b) return outputs
2、導入數據
這里構建一個方程 y = x^2 -0.5有噪聲的數據,x_data 和 y_data,noise表示噪聲,均值為o,方差為0.05
x_data = np.linspace(-1,1,300, dtype=np.float32)[:, np.newaxis] noise = np.random.normal(0, 0.05, x_data.shape).astype(np.float32) y_data = np.square(x_data) - 0.5 + noise
利用占位符定義我們所需的神經網絡的輸入。 tf.placeholder()
就是代表占位符,這里的None
代表無論輸入有多少都可以,因為輸入只有一個特征,所以這里是1
。
xs = tf.placeholder(tf.float32, [None, 1]) ys = tf.placeholder(tf.float32, [None, 1])
3、搭建網絡
神經網絡的結構通常包含輸入層、隱藏層和輸出層。由於我們的輸入數據比較簡單,所以我們的輸入層就是我們的導入數據部分;隱藏層我們可以根據具體情況自定義結構,這里我們設置神經元個數為10個,該層輸入大小即輸入層輸出的大小為1,有十個神經元,所以輸出數據大小為10。激活函數為None時使用的是TensorFlow自帶的激活函數 tf.nn.relu 。
l1 = add_layer(xs, 1, 10, activation_function=tf.nn.relu)
輸出層的輸入就是隱藏層的輸出,所以輸入大小為10,輸出大小為1,輸出層的輸出數據即為模型的預測值。
prediction = add_layer(l1, 10, 1, activation_function=None)
接下來求loss值,計算預測值 prediction 和真實值的誤差,對二者差的平方求和再取平均。
loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction),reduction_indices=[1]))
然后就是使用優化函數讓機器學習模型在訓練過程中提升准確率,最基本的優化函數是 tf.train.GradientDescentOptimizer() 中的值通常都小於1,這里取的是 0.1,代表學習率為0.1,以0.1的效率最小化誤差loss。
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
設置完變量,神經層,誤差計算,訓練優化函數之后剩下的就是變量的初始化,定義session,對session進行初始化,最后運行session。
init = tf.global_variables_initializer() # 初始化所有變量 sess = tf.Session() sess.run(init)
4、訓練模型
讓之前構建好的神經網絡模型訓練1000回合,機器學習的內容已經設置好是train_step,用Session來run每一次的train,當運算要用到placeholder
時,就需要feed_dict
這個字典來指定輸入。
for i in range(1000): # training sess.run(train_step, feed_dict={xs: x_data, ys: y_data}) if i % 50 == 0: # to see the step improvement print(sess.run(loss, feed_dict={xs: x_data, ys: y_data}))
5、(數據可視化)
利用matplotlib.pyplot庫將原本數據和訓練好的數據可視化。
# 可視化數據 fig = plt.figure() ax = fig.add_subplot(1,1,1) ax.scatter(x_data,y_data) # 訓練模型 for i in range(1000): sess.run(train_step,feed_dict={xs:x_data,ys:y_data}) if i%50 == 0: print(sess.run(loss,feed_dict={xs:x_data,ys:y_data})) prediction_value = sess.run(prediction,feed_dict={xs:x_data}) lines = ax.plot(x_data,prediction_value,'r-',lw=5) plt.show()
完整代碼如下:
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt def add_layer(inputs,in_size,out_size,activation_function=None): Weights = tf.Variable(tf.random_normal([in_size,out_size]),name='w') biases = tf.Variable(tf.zeros([1,out_size]) + 0.1,name='b') Wx_plus_b = tf.matmul(inputs,Weights) + biases if activation_function is None: outputs = Wx_plus_b else: outputs = activation_function(Wx_plus_b) return outputs x_data = np.linspace(-1,1,300)[:,np.newaxis] noise = np.random.normal(0,0.05,x_data.shape) y_data = np.square(x_data) - 0.5 + noise xs = tf.placeholder(tf.float32,[None,1],name='x_input') ys = tf.placeholder(tf.float32,[None,1],name='y_input') # 添加隱藏層 L1 = add_layer(xs,1,10,activation_function=tf.nn.relu) # 添加輸出層 prediction = add_layer(L1,10,1,activation_function=None) loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction),reduction_indices=[1])) train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss) init = tf.initialize_all_variables() sess = tf.Session() writer = tf.summary.FileWriter('./logs',sess.graph) sess.run(init) # 可視化數據 fig = plt.figure() ax = fig.add_subplot(1,1,1) ax.scatter(x_data,y_data) # 訓練模型 for i in range(1000): sess.run(train_step,feed_dict={xs:x_data,ys:y_data}) if i%50 == 0: print(sess.run(loss,feed_dict={xs:x_data,ys:y_data})) prediction_value = sess.run(prediction,feed_dict={xs:x_data}) lines = ax.plot(x_data,prediction_value,'r-',lw=5) plt.show()
3.classification
任務:使用神經網絡模型將一組代表0-9數字的圖片按照數字進行分類,使用的數據為MNIST庫,如果導入失敗可以下載該數據,將tutorials文件夾放入python安裝目錄的 \python3.7\Lib\site-packages\tensorflow_core\examples\文件夾中,tensorflow官方github中不知道為什么已經沒有這個文件夾了,所以我把這個文件夾的微雲鏈接放在這里tutorials。分類模型的完整代碼如下:
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data # 讀取樣本數據 mnist = input_data.read_data_sets('MNIST_data',one_hot=True) # 定義添加層函數 def add_layer(inputs,in_size,out_size,activation_function=None): Weights = tf.Variable(tf.random_normal([in_size,out_size])) biases = tf.Variable(tf.zeros([1,out_size]) + 0.1) Wx_plus_b = tf.matmul(inputs,Weights) + biases if activation_function is None: outputs = Wx_plus_b else: outputs = activation_function(Wx_plus_b) return outputs def compute_accuracy(v_xs,v_ys): global prediction y_pre = sess.run(prediction,feed_dict={xs:v_xs}) correct_prediction = tf.equal(tf.argmax(y_pre,1),tf.argmax(v_ys,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) result = sess.run(accuracy,feed_dict={xs:v_xs,ys:v_ys}) return result # 784 = 28*28個像素點 xs = tf.placeholder(tf.float32,[None,784]) # 10種數字類型 ys = tf.placeholder(tf.float32,[None,10]) # 添加輸出層 prediction = add_layer(xs,784,10,activation_function=tf.nn.softmax) # 計算loss cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys*tf.log(prediction),reduction_indices=[1])) train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) sess = tf.Session() sess.run(tf.initialize_all_variables())
print('每一輪的准確率如下:') for i in range(1000): batch_xs,batch_ys = mnist.train.next_batch(100) sess.run(train_step,feed_dict={xs:batch_xs,ys:batch_ys}) if i % 50 == 0: print(compute_accuracy(mnist.test.images,mnist.test.labels))