在 昨天的文章 安裝完 TensorFlow,之後,今天讓我們來看看怎麼用 TenforFlow 來實作梯度下降
# 載入套件
import tensorflow as tf
import numpy as np
# 訓練資料
x_data = np.array([ 9, 4, 7 , 3 , 10 , 7 , 4 , 3 , 1, 9])
y_data = np.array([ 45 , 24 , 59 , 28 , 91 , 28 , 42 , 18 , 14, 82])
這邊跟我們先前的做法是一樣的
# 假設模型為 y = a * x + b
# 模型參數
a = tf.Variable([7], dtype=tf.float32)
b = tf.Variable([2], dtype=tf.float32)
# 定義變數
x = tf.placeholder(tf.float32)
y = tf.placeholder(tf.float32)
這裡我們假設模型還是 y = a * x + b
,先用 tf.Variable
的方法定義了 a 和 b 的初始值,以及用 tf.placeholder
創造出未來存放 x 與 y 值的地方。其中 Variable 和 Placeholder 是兩種 TensorFlow 當中的資料型態。
Variable 顧名思義就就是變數,和我們在一般的程式語言使用的方法一樣,但是在 TensorFlow 有兩個需要注意的地方,第一個是當我們宣告一個變數的時候,除了給定初始值外,也可以定義他的類型,另外,在使用前需要初始化,待會在後面的程式我們將會看到初始化的地方。Variable 的值除了可以是單一的數字之外,也可以是數列或陣列,像是
variable_1 = tf.Variable(17,dtype=tf.float32)
variable_2 = tf.Variable([17,27],dtype=tf.float32)
Placeholder 顧名思義就是一個先佔有空間的東西,這裡可以想像是我們創造了一個佔有一定空間的空白陣列,一樣我們也可以先指定這個 placeholder 裡面的值得資料型態,以及它的 shape。
variable 跟 placeholder 看起來都是可以存放數值的東西,那麼兩者差在哪裡呢?在實作上,通常會把需要被訓練的變數設定為 variable,譬如在我們的案例裡,就是 a
和 b
(兩個我們想要透過機器訓練出來的結果),在過程中這裡兩個會不斷的變化;而 placeholder 主要會放置我們提供的訓練資料,像是最一開的 x_data 和 y_data
# 定義模型
linear_model = a*x + b
# 損失函數
loss = tf.reduce_sum(tf.square(linear_model - y))
# 優化器 optimizer
optimizer = tf.train.GradientDescentOptimizer(0.00001)
train = optimizer.minimize(loss)
這裡我們定義了 model 的樣子,以及損失函數該怎麼計算。接著,就到了 TensorFlow 厲害的地方了,這裡我們可以選擇不同的「優化器 optimizer」來幫助我們訓練機器。在 TenforFlow 當中有很多種優化器,也就是不同的算法,像是
這裡我們選擇了 GradientDescentOptimizer,另外也定義了 learning rate 0.00001
,以及訓練的目的:最小化損失函數
# 執行梯度下降
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
for i in range(100000):
sess.run(train, {x: x_data, y: y_data})
這裡我們先初始化變數,接著用 sess 來執行 初始化 (init) 以及我們剛剛決定好的 訓練方式 (train)。在 TensorFlow 的世界當中,基本上做任何事情都得靠 tf.Session() 來幫忙。
把上面提到的程式碼組合起來之後,就可以開始跑訓練囉!完成之後,再用下面的方法把訓練完的結果給印出來(你看這邊連印個變數的值都要用 sess.run() 來看)
print(sess.run(a))
print(sess.run(b))
print(sess.run(loss, {x: x_data, y: y_data}))
結果如下
[7.215693] #a
[1.9708481] #b
1879.5819 #loss
回頭看看一樣用 learning rate 為 0.00001、iteration 為 100000 的情況下,用我們自己寫的 Python code 的結果
7.20311491829791 #a
2.061284742936665 #b
1879.599863360517 #loss
會發現兩者之間是有小小的差異的(好吧,我承認不知道這個差異真正是從哪裡來的)
我們用 TensorFlow 實現了梯度下降的方式來訓練機器,看起來的確是比自己寫 Python code 還要來得簡單多了。明天讓我們來繼續探索 TensorFlow 吧!