1. 程式人生 > >Keras和TensorFlow之爭何時休?

Keras和TensorFlow之爭何時休?

實際上,到 2017 年中,Keras 已經被大規模採用,並與 TensorFlow 整合在一起。這種 TensorFlow + Keras 的組合讓你可以:

 ●  使用 Keras 的介面定義模型;
 ●  如果你需要特定的 TensorFlow 功能或者需要實現 Keras 不支援但 TensorFlow 支援的自定義功能,可以回到 TensorFlow。

簡單地說,你可以將 TensorFlow 程式碼直接插入到 Keras 的模型或訓練管道中!

但請別誤會,我並不是說你就不需要了解 TensorFlow 了。我的意思是,如果你:

 ●  剛開始接觸深度學習……
 ●  在為下一個專案選型……
 ●  想知道 Keras 或 TensorFlow 哪個“更好”……

我的建議是先從 Keras 著手,然後深入 TensorFlow,這樣可以獲得你需要的某些特定功能。

在這篇文章中,我將向你展示如何使用 Keras 訓練神經網路,以及如何使用直接構建在 TensorFlow 庫中的 Keras + TensorFlow 組合來訓練模型。

Keras 與 TF 我該學哪個?

在文章的其餘部分,我將繼續討論有關 Keras 與 TensorFlow 的爭論以及為什麼說這個問題其實是個錯誤的問題。

我們將使用標準的 keras 模組以及 TensorFlow 的 tf.keras 模組實現一個卷積神經網路(CNN)。

我們將在一個樣本資料集上訓練 CNN,然後檢查結果——你會發現,Keras 和 TensorFlow 可以很融洽地合作。

最重要的是,你將會了解為什麼 Keras 與 TensorFlow 之間的爭論其實是沒有意義的。

儘管從 TensorFlow 宣佈將 Keras 整合到官方 TensorFlow 版本中已經一年多時間了,但很多深度學習從業者仍然不知道他們可以通過 tf.keras 子模組訪問 Keras,為此我感到很驚訝。

更重要的是,Keras + TensorFlow 的整合是無縫的,你可以直接將 TensorFlow 程式碼放到 Keras 模型中。

在 TensorFlow 中使用 Keras 將為你帶來兩全其美的好處:

 ●  你可以使用 Keras 提供的簡單直觀的 API 來建立模型;
 ●  Keras API 與 scikit-learn(被認為是機器學習 API 的“黃金標準”)很像;
 ●  Keras API 採用了模組化,易於使用;
 ●  當你需要自定義實現或者更復雜的損失函式時,可以直接進入 TensorFlow,並讓程式碼自動與 Keras 模型整合。

在過去幾年中,深度學習研究人員、從業人員和工程師通常需要做出以下選擇:

 ●  我是選擇易用但難以定製的 Keras 庫?
 ●  還是選擇難用的 TensorFlow API,並編寫更多的程式碼?

所幸的是,我們不必再糾結了。

如果你發現自己還在問這樣的問題,那麼請退後一步——你問的是錯誤的問題——你可以同時擁有這兩個框架。

dc2d1d20072bd98c9ea77c0bcfdc9cb30459bb19

如圖所示,匯入 TensorFlow(tf),然後呼叫 tf.keras,可見 Keras 實際上已經成為 TensorFlow 的一部分。

在 tf.keras 中包含 Keras 讓你可以使用標準的 Keras 包實現簡單的前饋神經網路:

ef0a440807a662f7ff64da9725e18d361019b7b6

然後使用 tf.keras 子模組實現相同的網路:

9f1aa80789cc9fcd351f4ac2121d772c5cb7379e

這是否意味著你必須使用 tf.keras?標準的 Keras 包是不是已經過時?當然不是。

作為一個庫,Keras 仍然可以單獨使用,因此未來兩者可能會分道揚鑣。不過,因為谷歌官方支援 Keras 和 TensorFlow,所以似乎不太可能出現這種情況。

關鍵是:

如果你習慣使用 Keras 編寫程式碼,那麼請繼續這樣做。

但如果你主要使用的是 TensorFlow,那麼應該開始考慮一下 Keras API:

 ●  它內置於 TensorFlow 中;
 ●  它更容易使用;
 ●  當你需要使用 TensorFlow 來實現特定功能時,可以直接將其整合到 Keras 模型中。

我們的樣本資料集

fbd3bb569aca8f5d166ff5c96bce7be102e80406

CIFAR-10 資料集包含了 10 個分類,我們將它用在我們的演示中。

為簡單起見,我們將使用以下方法在 CIFAR-10 資料集上訓練兩個單獨的卷積神經網路:

 ●  TensorFlow + Keras;
 ●  tf.keras 的 Keras 子模組。

我還將展示如何將自定義的 TensorFlow 程式碼包含在 Keras 模型中。

我們的專案結構

可以使用 tree 命令在終端中檢視我們的專案結構:

2bee9e0c401a1fb2349418223184265a3cccb8ed

pyimagesearch 模組不能通過 pip 安裝,請點選文末提供的下載連結。現在讓我們看一下該模組的兩個重要 Python 檔案:

 ●  minivggnetkeras.py:MiniVGGNet(一個機遇 VGGNet 的深度學習模型)的 Keras 實現。
 ●  minivggnettf.py:MiniVGGNet 的 TensorFlow + Keras(即 tf.keras)實現。

專案根目錄包含兩個 Python 檔案:

 ●  train_network_keras.py:Keras 版本的訓練指令碼。
 ●  train_network_tf.py:TensorFlow + Keras 版本的訓練指令碼,幾乎與前一個一模一樣。

每個指令碼都將生成相應的訓練準確率和損失:

 ●  plot_keras.png
 ●  plot_tf.png

使用 Keras 訓練網路

1162bb30f8dde8ecc46b65daf8107764b2d19f53

訓練的第一步是使用 Keras 實現網路架構。

開啟 minivggnetkeras.py 檔案,並插入以下程式碼:

4fcea52c79bf7e43c60b0443fb7c1ade4f064e6d

我們先匯入構建模型需要的一系列 Keras 包。

然後定義我們的 MiniVGGNetKeras 類:

ae1c14ff2bfcd5ef4e750eeb4def839ca016e9a3

我們定義了 build 方法、inputShape 和 input。

然後定義卷積神經網路的主要部分:

156ca047136d35290d545ac19e5d9c570b2b355b

你會發現我們在應用池化層之前堆疊了一系列卷積、ReLU 啟用和批量規範化層,以便減少卷的空間維度。還使用了 Dropout 來減少過擬合。

現在將全連線層新增到網路中:

150f44b440bd994d5225aeb62f7bb890ee7dbfc6

我們已經使用 Keras 實現了 CNN,現在建立將用於訓練的驅動指令碼。

開啟 train_network_keras.py 並插入以下程式碼:

e0cca3d160e3f0d48f1fced0ef3fe0b876cead38

我們先匯入需要的包。

 ●  matplotlib 設定為“Agg”,這樣就可以將訓練結果儲存為影象檔案。
 ●  然後匯入 MiniVGGNetKeras 類。
 ●  我們使用 scikit-learn 的 LabelBinarizer 進行“獨熱”編碼,並使用 classification_report 列印分類精度。
 ●  然後匯入資料集。

我們通過 --plot 傳入命令列引數,也就是影象的儲存路徑。

現在讓我們載入 CIFAR-10 資料集,並對標籤進行編碼:

d55e70e06057eb6d01bf41512657715ee6aaa95a

我們先載入和提取訓練和測試分割,並將它們轉換為浮點數和進行資料縮放。

然後我們對標籤進行編碼,並初始化 labelNames。

接下來,讓我們開始訓練模型:

4ef385d387c0fde1fc8171f28a935bdb55f84678

我們先設定訓練引數和優化方法。

然後我們使用 MiniVGGNetKeras.build 方法初始化和編譯模型。

隨後,我們啟動了訓練程式。

現在讓我們來評估網路並生成結果圖:

56932c90e053d5509cb7012b58c59b8a29ca220b

我們基於資料的測試分割來評估網路,並生成 classification_report,最後再匯出結果。

注意:通常我會序列化並匯出模型,以便可以將其用在影象或視訊的處理指令碼中,但這裡不打算這樣做,因為這超出了本文的範圍。

開啟一個終端並執行以下命令:

17944b33ae15f25887a97435f09eb4cdadc96b1b

我的 CPU 完成一個 epoch 需要 5 分多鐘。

8c4c849292359772585717e45da67b2c09bc12a2

我們獲得了 75%的準確率——當然不是最先進的,不過它比隨機猜測(1/10)要好得多。

對於小型網路來說,我們的準確率算是非常好的了,而且沒有發生過擬合。

使用 TensorFlow 和 tf.keras 訓練網路

使用 tf.keras 構建的 MiniVGGNet CNN 與我們直接使用 Keras 構建的模型是一樣的,除了為演示目的而修改的啟用函式。

現在我們已經使用 Keras 庫實現並訓練了一個簡單的 CNN,接下來我們要:

 ●  使用 TensorFlow 的 tf.keras 實現相同的網路;
 ●  在 Keras 模型中包含一個 TensorFlow 啟用函式,這個函式不是使用 Keras 實現的。

首先,開啟 minivggnettf.py 檔案,我們將實現 TensorFlow 版本的 MiniVGGNet:

e5c881fa66dc1b6de5ed5d100782c7149ce3538a

請注意,匯入部分只有一行。tf.keras 子模組包含了我們可以直接呼叫的所有 Keras 函式。

我想強調一下 Lambda 層——它們用來插入自定義啟用函式 CRELU(Concatenated ReLU)。

Keras 並沒有實現 CRELU,但 TensorFlow 實現了——通過使用 TensorFlow 和 tf.keras,我們可以使用一行程式碼將 CRELU 新增到 Keras 模型中。

下一步是編寫 TensorFlow + Keras 驅動指令碼來訓練 MiniVGGNetTF。

開啟 train_network_tf.py 並插入以下程式碼:

ae231255fd7b5d103272d175ffd458134b403095

然後是解析命令列引數。

接著像之前一樣載入資料集。

其餘的行都一樣——提取訓練 / 測試分割和編碼標籤。

現在讓我們開始訓練模型:

fd58365005f7c37df1ea1a6050f9930f478e6f36

訓練過程幾乎是一樣的。我們已經實現了完全相同的訓練流程,只是這次使用的是 tf.keras。

開啟一個終端並執行以下命令:

e0cab606ede0a2fda6df4518b61e191b18f0257a

訓練完成後,你將獲得類似於下面這樣的結果:

46c9e9807ce85a6e15fb6e7d3c5e2e1cd212bc02

通過使用 CRELU 替換 RELU 啟用函式,我們獲得了 76%的準確率。不過,這 1%的提升可能是因為網路權重的隨機初始化,需要通過進一步的交叉驗證實驗來證明這種準確率的提升確實是因為 CRELU。

不管怎樣,原始準確率並不是本節的重點。我們需要關注的是如何在 Keras 模型內部使用 TensorFlow 啟用函式替換標準的 Keras 啟用函式!

你也可以使用自己的自定義啟用函式、損失 / 成本函式或層。

總 結

在這篇文章中,我們討論了 Keras 和 TensorFlow 相關的問題,包括:

 ●  我應該在專案中使用 Keras 還是 TensorFlow?
 ●  TensorFlow 和 Keras 哪個更好?
 ●  我應該花時間研究 TensorFlow 還是 Keras?

最後我們發現,在 Keras 和 TensorFlow 之間做出選擇變得不那麼重要。

因為 Keras 庫已經通過 tf.keras 模組直接整合到 TensorFlow 中了。


原文釋出時間為:2018-11-1

本文作者:AI前線小組

本文來自雲棲社群合作伙伴“磐創AI”,瞭解相關資訊可以關注“磐創AI”。