- TensorFlow 2.0卷積神經網絡實戰
- 王曉華
- 2527字
- 2020-04-24 14:11:18
2.1 配角轉成主角——從TensorFlow Eager Execution轉正談起
最早追溯到TensorFlow 1.10版本,那個時候TensorFlow由于強大的深度學習計算能力被眾多的深度學習從業人員所使用。但是盛名之下還是有一些小的確定讓人詬病,例如程序編寫的困難,代碼格式和其他深度學習框架有較大差異,運行時占用資源較多等。
TensorFlow開發組為了解決這些問題,在TensorFlow 1.10版本的時候就引入了一種新的程序運行機制——TensorFlow Eager Execution。其目的是為了解決程序開發人員使用TensorFlow作為深度學習框架時學習坡度不是很友善的缺點,同時也為了增加程序編寫的方便,使用了一種新的簡化的TensorFlow運行機制Eager Execution。結果一經推出就大受好評,使得很多原先使用別的機器學習框架的程序編寫人員、機器學習愛好者轉投TensorFlow的懷抱中。
TensorFlow Eager Execution(動態圖)是一個命令式的編程環境,不建立圖而是立即運算求值:運算返回具體值替換(以前)先構建運算圖然后執行的機制。使得(使用)TensorFlow和調試模型變得簡單,而且減少了多余(模板化、公式化操作)。
動態圖是一個靈活的機器學習平臺,用于研究和實驗,提供以下功能:
●直觀的接口:方便編碼使用,基于Python數據結構。快速迭代小模型和小數據。
●調試簡單:直接調用ops來檢查運行模型和測試變更。使用標準Python調試工具進行即時錯誤報告。
●自然控制流:使用Python控制流替換圖控制流,簡化動態模型規范。
2.1.1 Eager簡介與調用
TensorFlow的開發團隊曾經表示,Eager Execution的主要優點如下:
●快速調試即刻的運行錯誤并通過Python工具進行整合。
●借助易于使用的Python控制流支持動態模型。
●為自定義和高階梯度提供強大的支持。
●適用于幾乎所有可用的TensorFlow運算。
1. Eager Execution的調用
Eager Execution的調用非常簡單,可以直接使用代碼如下:

這是因為在TensorFlow 2.0中,Eager Execution是默認開啟的,因此直接引入TensorFlow即可。
而在TensorFlow 1.X版本中,Eager Execution需要手動開啟,代碼如下:

這些代碼是在1.X版本中開啟Eager Execution的方法,首先第1行是引入TensorFlow,第2~3行是顯示調用Eager模式,使之可以在本段代碼中使用。
此外,更為常見的是,讀者安裝了TensorFlow 2.0或者更高版本,對于運行在1.X版本下編寫的代碼,可能會產生一些問題。因此需要重新引入TensorFlow 1.X的運行模式,在引入TensorFlow的時候需要修改代碼如下:

這樣顯式地調用TensorFlow 1.X版本的API使用。
2. Eager模式的使用
Eager Execution一個非常有意思的、作為宣傳點的功能就是允許用戶在不創建Graph(圖)的情況下運行TensorFlow代碼,代碼如下:
【程序2-1】

這里默認啟動了Eager模式,在使用TensorFlow讀入一個序列后將其打印,結果如下:

可以看到,結果打印出了讀入數據后的Tensor數據格式,即具體數值為[1,2],維度大小為2,數據類型為int32。
如果此時需要將這個數據的具體內容打印出來,代碼可以改成如下:
【程序2-2】

打印結果如下:

可以看到,此時由于加上了數據自帶的numpy()函數,Tensor數據被顯示轉化為常用的NumPy數據格式,即常數格式。
這里順帶提一下,如果使用傳統的TensorFlow編寫模式,代碼要修改為:
【程序2-3】

打印結果如下:

可以看到,此時數據被讀入到圖中而不是被直接計算,因此打印出的結果并沒有具體數據,而具體數據的計算請讀者自行完成。
2.1.2 讀取數據
TensorFlow 1.X數據的讀取是采用占位符的形式,首先將數據讀取到內存中,之后建立整體的TensorFlow圖,在運行圖以后讀取數據并顯示。
TensorFlow 2.0簡化了數據讀取,其相似度NumPy的數據迭代風格,只使用TensorFlow中自帶的Dateset API即可完成數據的迭代,代碼如下:
1. 第一步:生成數據

首先是數據的生成,作者使用Numpy做了數據生成,產生了100個由0~99的數據并存儲在arr_list中。
2. 第二步:使用Dataset API讀取數據
下面使用Dataset讀取API,代碼如下:

這里首先使用Dataset.from_tensor_slices讀取數據,之后使用shuffle函數打亂順序,最終將數據以每個batch為10輸出。
3. 第三步:創建計算模型
創建計算模型是數據處理的關鍵,這里為了簡化起見,作者創建了一個非常簡單的模型,即使用TensorFlow將輸入的數據乘以0.1并輸出,代碼如下:

這里的model是一個簡單函數的實現,有興趣的讀者可以往里添加更多的內容。
4. 第四步:數據的迭代輸出
最后就是讀取數據的迭代輸出,前面已經做了說明,在Eager模式中,Dataset API是可以自動生成一個新的迭代器,將數據迭代出來。代碼如下:

這樣就構成了一個完整的使用Eager模型進行簡單數據計算的模型,全部代碼如下:
【程序2-4】

最終打印結果如圖2.2所示。

圖2.2 打印結果
輸出結果顯然不符合在程序中既定的模型,即將數列中的數乘以0.1并顯示,而這里的輸出數據卻都顯示為0。
究其原因是在Numpy數據生成的時候,以int32格式為數據的基本生成格式,因此Eager在進行計算時無法隱式地將數據轉化成float類型,從而造成計算失敗。
解決的辦法也很方便,將數據生成代碼改成如下形式:

具體內容請讀者自行完成。
2.1.3 使用TensorFlow 2.0模式進行線性回歸的一個簡單的例子
下面我們就以一個線性回歸的模型為例,介紹使用Eager模型進行機器學習計算的方法,其中涉及到模型參數的保存,以及讀取已經保存的模型重新計算。
1. 第一步:模型的工具與數據的生成
首先是模型的定義,這里我們使用一個簡單的一元函數模型作為待測定的模型基礎,公式如下:

即3倍的輸入值加上0.217作為輸出值。
2. 第二步:模型的定義
在這里由于既定的模型是一個一元線性方程,因此在使用Eager模型時自定義一個類似的數據模型,代碼如下:

首先使用固定數據定義模型初始化參數weight和bias,之后一個線性回歸模型在初始狀態擬合了一元回歸模型。
3. 第三步:損失函數的定義
對于使用機器學習進行數據擬合,一個非常重要的內容就是損失函數的編寫,它往往決定著數據從空間中的哪個角度去擬合真實數據。
本例使用均方差(MSE)去計算擬合的數據與真實數據之間的誤差,代碼如下:

這是使用TensorFlow自帶損失函數計算MSE(均方差)的表示方法,當然也可以使用自定義的損失函數,代碼如下:

這兩者是等效的,不過自定義的損失函數可以使程序編寫者獲得更大的自由度,對新手來說,還是使用定制的損失函數去計算較好,這一點請讀者自行斟酌。
4. 第四步:梯度函數的更新計算
下面就是梯度的函數計算,這里可以直接調用TensorFlow的優化器,作者選擇使用Adam優化器作為優化工具,代碼如下:

opt對應的是TensorFlow優化器的對應寫法。全部代碼如下:
【程序2-5】

打印結果如圖2.3所示。

圖2.3 打印結果
可以看到經過迭代計算以后,生成的weight值和bias值較好地擬合成預定的數據。有TensorFlow 1.X編程經驗的讀者可能會對這種數據更新的方式不習慣,但是需要記住這種寫法:

除此之外Keras對于梯度的更新采用回調的方式對權重進行更新,代碼如下:

全部代碼如下(函數調用過于復雜,僅供參考):
【程序2-6】

在這里函數會直接調用,其內部多次用到回調函數,對Python有較多研究的讀者可以嘗試運行一下。