Tensorflow入門——Eager模式像原生Python一樣簡潔優雅

image source from unsplash.com by Sergio souza

衆所周知,Tensorflow入門之所以困難,與其採用的Graph 和 Session 模式有關,這與原生的 Python 代碼簡單、直觀的印象格格不入。同時,由於計算僅僅發生在Session裏面,所以初始化參數和變量的時候沒辦法將結果打印出來,以至於調試起來也十分困難。

當然Google官方也意識到了這點,於是引入了Eager模式,在這個模式下tensorflow的常量和變量可以直接計算並打印出來,甚至還可以和numpy數組混合計算。本文代碼參考官方教程(from github with Apache License 2.0)

同樣的,爲了方便與讀者交流,所有的代碼都放在了這裏:

https://github.com/zht007/tensorflow-practice

1. 激活Eager模式

激活Eager模式也非常簡單,僅幾行代碼。

import tensorflow as tf
tf.enable_eager_execution()
tfe = tf.contrib.eager

注意,eager模式在程序開始就要激活,且不能與普通模式混用。另外tfe在後面優化器(Optimizer)的時候需要用到,故先在這裏定義了。

2. Eger模式上手

Eger模式下,定義的變量或者常量可以直接打印出來

a = tf.constant([[1, 2],
                 [3, 4]])
print('a=',a)

b = tf.Variable(np.zeros((2,2)))

print('\n b=',b)

c = tf.Variable([[6, 7],
                 [8, 9]])

print('\n c=',c)

-------output-------
a= tf.Tensor(
[[1 2]
 [3 4]], shape=(2, 2), dtype=int32)

 b= <tf.Variable 'Variable:0' shape=(2, 2) dtype=float64, numpy=
array([[0., 0.],
       [0., 0.]])>

 c= <tf.Variable 'Variable:0' shape=(2, 2) dtype=int32, numpy=
array([[6, 7],
       [8, 9]], dtype=int32)>

可以直接轉換成我們熟悉的numpy arrary

print(c.numpy())

---output---
[[6 7]
 [8 9]]

當然也可以直接計算並輸出結果,甚至可以與numpy arrary 混合計算。

x = tf.Variable([[6, 7],
                 [8.0, 9.0]],dtype ="float32")
y = np.array([[1,2],
              [3,4]],dtype ="float32")

print(tf.matmul(x,y))
----output----
tf.Tensor(
[[27. 40.]
 [35. 52.]], shape=(2, 2), dtype=float32)

3. Eager 模式下訓練線性迴歸模型

最後我們用Tensor Flow 在Eager模式下訓練線性迴歸模型,該模型我們之前已經用Tensorflow和Keras訓練過了,感興趣的朋友可以參照之前的文章進行對比。

3.1 創建模擬數據

與之前的數據一樣,此處數據是100萬個帶噪音的線性數據,100萬個點用plt是畫不出來的,圖中隨機採樣了250個點

我們定義一個幫助函數方便以batch的形式這100萬個數據點中隨機抽取batch size大小的數據進行訓練

def next_batch(x_data, batch_size):
    batch_index = np.random.randint(len(x_data),size=(BATCH_SIZE))
    x_train = x_data[batch_index]
    y_train = y_true[batch_index]
    return x_train, y_train

3.2 定義變量

此處與普通模式下的tensorflow變量沒有任何區別

w_tfe = tf.Variable(np.random.uniform())
b_tfe = tf.Variable(np.random.uniform(1,10)

3.3 線性函數

在普通模式下的tensorflow中我們需要定義計算圖譜,這裏我們直接以 python 函數的形式,定義要訓練的線性迴歸函數。

def linear_regression(inputs):
    return inputs * w_tfe + b_tfe

3.4 損失函數

同樣的,MS(Mean Square)損失函數也要以python 函數的形式定義,而不是計算圖譜。

def mean_square_fn(model_fn, inputs, labels):
    return tf.reduce_sum(tf.pow(model_fn(inputs) - labels, 2)) / (2 * BATCH_SIZE)

3.5 優化器

同樣使用Gradient Descent 的優化器,不同在於,普通模式下我們創建一個計算圖譜train = optimizer.minimize(error), 在Eager模式下,要用tfe.implicit_gradients()來返回一個函數。

optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)

grad = tfe.implicit_gradients(mean_square_fn)

3.6 模型訓練

由於沒有計算圖譜,所以也不需要初始化變量,也不需在Session下運行,而是類似於原生 Python 函數的形式將數據傳入"Optimizer模型"函數。訓練完成之後,w 和 b 的參數也自動保存下來,不必在Session中提取。

for step in range(BATCHS):
    
    x_train, y_train = next_batch(x_data, BATCH_SIZE)
    optimizer.apply_gradients(grad(linear_regression, x_train, y_train))

3.7 驗證訓練結果

直接將最終的 w 和 b 帶入線性函數,訓練結果也非常符合預期。

4. 總結

Eager 模式下的 Tensorflow 與原生的 Python 代碼非常類似,可以直接計算並打印結果,創建和訓練模型的過程也類似於python函數的創建和調用。Eager 和Keras API 都是Tensorflow 2.0 官方主推的 Tensorflow使用方式,相信在不久的將來,獲取我們就再也看不到 init = tf.global_variables_initializer() 還有 with tf.Session() as sess:這樣的類似八股文一樣的關鍵詞啦。


參考資料

[1] Google Tensorflow 官方文檔和教程

[2] Github TensorFlow-Examples


相關文章

Tensorflow入門——線性迴歸

Tensorflow入門——Keras簡介和上手

AI學習筆記——Tensorflow入門


首發steemit

歡迎掃描二維碼關注我的微信公衆號“tensorflow機器學習”,一起學習,共同進步

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章