使用 Keras + TensorFlow 開發一個複雜深度學習模型
本帖最後由 Oner 於 2017-5-25 19:37 編輯
問題導讀:
1. 爲什麼選擇Keras?
2. 怎麼安裝Keras,並且把TensorFlow作爲後端?
3. Keras序列模型是什麼?
4. 如何使用 Keras 保存和恢復預訓練的模型?
5. 如何使用Keras API開發VGG卷積神經網絡?
6. 如何使用Keras API構建並運行SqueezeNet卷積神經網絡?
Keras 是提供一些高可用的 Python API ,能幫助你快速的構建和訓練自己的深度學習模型,它的後端是 TensorFlow 或者 Theano 。本文假設你已經熟悉了 TensorFlow 和卷積神經網絡,如果,你還沒有熟悉,那麼可以先看看這個10分鐘入門 TensorFlow 教程[http://cv-tricks.com/artificial- ... ensorflow-tutorial/]和卷積神經網絡教程[http://cv-tricks.com/tensorflow- ... age-classification/],然後再回來閱讀這個文章。
在這個教程中,我們將學習以下幾個方面:
1. 爲什麼選擇Keras?
Keras 是 Google 的一位工程師 François Chollet [https://twitter.com/fchollet]開發的一個框架,可以幫助你在 Theano 上面進行快速原型開發。後來,這被擴展爲 TensorFlow 也可以作爲後端。並且最近,TensorFlow決定將其作爲 contrib 文件中的一部分進行提供。
Keras 被認爲是構建神經網絡的未來,以下是一些它流行的原因:
想象一下,我們每年都要去學習一個新的框架,這是多麼的痛苦。到目前爲止,TensorFlow 似乎成爲了一種潮流,並且越來越多的框架開始爲 Keras 提供支持,它可能會成爲一種標準。
目前,Keras 是成長最快的一種深度學習框架。因爲可以使用不同的深度學習框架作爲後端,這也使得它成爲了流行的一個很大的原因。你可以設想這樣一個場景,如果你閱讀到了一篇很有趣的論文,並且你想在你自己的數據集上面測試這個模型。讓我們再次假設,你對TensorFlow 非常熟悉,但是對Theano瞭解的非常少。那麼,你必須使用TensorFlow 對這個論文進行復現,但是這個週期是非常長的。但是,如果現在代碼是採用Keras寫的,那麼你只要將後端修改爲TensorFlow就可以使用代碼了。這將是對社區發展的一個巨大的推動作用。
2. 怎麼安裝Keras,並且把TensorFlow作爲後端 a) 依賴安裝
安裝 h5py,用於模型的保存和載入:
[Python]
還有一些依賴包也要安裝。
[Python]
如果你還沒有安裝TensorFlow,那麼你可以按照這個
教程先去安裝TensorFlow。一旦,你安裝完成了 TensorFlow,你只需要使用 pip 很容易的安裝 Keras。
[Python]
使用以下命令來查看 Keras 版本。
[Python]
一旦,Keras 被安裝完成,你需要去修改後端文件,也就是去確定,你需要 TensorFlow 作爲後端,還是 Theano 作爲後端,修改的配置文件位於
~/.keras/keras.json 。具體配置如下:
[Python]
請注意,參數
image_data_format 是
channels_last ,也就是說這個後端是 TensorFlow。因爲,在TensorFlow中圖像的存儲方式是
[height, width, channels],但是在Theano中是完全不同的,也就是
[channels, height, width]。因此,如果你沒有正確的設置這個參數,那麼你模型的中間結果將是非常奇怪的。對於Theano來說,這個參數就是
channels_first。
那麼,至此你已經準備好了,使用Keras來構建模型,並且把TensorFlow作爲後端。
3. Keras基礎知識
在Keras中主要的數據結構是
model ,該結構定義了一個完整的圖。你可以向已經存在的圖中加入任何的網絡結構。
[Python]
Keras 有兩種不同的建模方式:
在本文的下一節中,我們將學習Keras的Sequential models 和 Functional API的理論和實例。
在這一部分中,我將來介紹Keras Sequential models的理論。我將快速的解釋它是如何工作的,還會利用具體代碼來解釋。之後,我們將解決一個簡單的線性迴歸問題,你可以在閱讀的同時運行代碼,來加深印象。
以下代碼是如何開始導入和構建序列模型。
[Python]
接下來我們可以向模型中添加 Dense(full connected layer),Activation,Conv2D,MaxPooling2D函數。
[Python]
以下是如何將一些最流行的圖層添加到網絡中。我已經在卷積神經網絡教程[http://cv-tricks.com/tensorflow- ... age-classification/]中寫了很多關於圖層的描述。
1. 卷積層
這裏我們使用一個卷積層,64個卷積核,維度是33的,之後採用
relu 激活函數進行激活,輸入數據的維度是 `100100*32`。注意,如果是第一個卷積層,那麼必須加上輸入數據的維度,後面幾個這個參數可以省略。
[Python]
2. MaxPooling 層
指定圖層的類型,並且指定赤的大小,然後自動完成赤化操作,酷斃了!
[Python]
3. 全連接層
這個層在 Keras 中稱爲被稱之爲 Dense 層,我們只需要設置輸出層的維度,然後Keras就會幫助我們自動完成了。
[Python]
4. Dropout
[Python]
5. 扁平層
model.add(Flatten()) 4. 數據輸入
網絡的第一層需要讀入訓練數據。因此我們需要去制定輸入數據的維度。因此,
input_shape 參數被用於制定輸入數據的維度大小。
[Python]
在這個例子中,數據輸入的第一層是一個卷積層,輸入數據的大小是
224*224*3 。
以上操作就幫助你利用序列模型構建了一個模型。接下來,讓我們學習最重要的一個部分。一旦你指定了一個網絡架構,你還需要指定優化器和損失函數。我們在Keras中使用compile函數來達到這個功能。比如,在下面的代碼中,我們使用
rmsprop 來作爲優化器,
binary_crossentropy 來作爲損失函數值。
[Python]
如果你想要使用隨機梯度下降,那麼你需要選擇合適的初始值和超參數:
[Python]
現在,我們已經構建完了模型。接下來,讓我們向模型中輸入數據,在Keras中是通過 fit 函數來實現的。你也可以在該函數中指定
batch_size 和
epochs 來訓練。
[Python]
最後,我們使用
evaluate 函數來測試模型的性能。
[Python]
這些就是使用序列模型在Keras中構建神經網絡的具體操作步驟。現在,我們來構建一個簡單的線性迴歸模型。
問題陳述
在線性迴歸問題中,你可以得到很多的數據點,然後你需要使用一條直線去擬合這些離散點。在這個例子中,我們創建了100個離散點,然後用一條直線去擬合它們。
a) 創建訓練數據
TrainX 的數據範圍是 -1 到 1,TrainY 與 TrainX 的關係是3倍,並且我們加入了一些噪聲點。
[Python]
b) 構建模型
首先我們需要構建一個序列模型。我們需要的只是一個簡單的鏈接,因此我們只需要使用一個
Dense 層就夠了,然後用線性函數進行激活。
[Python]
下面的代碼將設置輸入數據 x,權重 w 和偏置項 b。然我們來看看具體的初始化工作。如下:
[Python]
現在,我們可以l利用自己構造的數據 trX 和 trY 來訓練這個線性模型,其中 trY 是 trX 的3倍。因此,權重
w 的值應該是 3。
我們使用簡單的梯度下降來作爲優化器,均方誤差(MSE)作爲損失值。如下:
[Python]
最後,我們使用
fit 函數來輸入數據。
[Python]
在經過訓練之後,我們再次打印權重:
[Python]
正如你所看到的,在運行 200 輪之後,現在權重非常接近於 3。你可以將運行的輪數修改爲區間 [100, 300] 之間,然後觀察輸出結構有什麼變化。現在,你已經學會了利用很少的代碼來構建一個線性迴歸模型,如果要構建一個相同的模型,在 TensorFlow 中需要用到更多的代碼。
5. 使用 Keras 保存和回覆預訓練的模型 HDF5 二進制格式
一旦你利用Keras完成了訓練,你可以將你的網絡保存在HDF5裏面。當然,你需要先安裝 h5py。HDF5 格式非常適合存儲大量的數字收,並從 numpy 處理這些數據。比如,我們可以輕鬆的將存儲在磁盤上的多TB數據集進行切片,就好像他們是真正的 numpy 數組一樣。你還可以將多個數據集存儲在單個文件中,遍歷他們或者查看
.shape 和
.dtype 屬性。
如果你需要信心,那麼告訴你,NASA也在使用 HDF5 進行數據存儲。h5py 是python對HDF5 C API 的封裝。幾乎你可以用C在HDF5上面進行的任何操作都可以用python在h5py上面操作。
保存權重
如果你要保存訓練好的權重,那麼你可以直接使用
save_weights 函數。
[Python]
載入預訓練權重
如果你想要載入以前訓練好的模型,那麼你可以使用
load_weights 函數。
[Python]
6. Keras API
如果對於簡單的模型和問題,那麼序列模型是非常好的方式。但是如果你要構建一個現實世界中複雜的網絡,那麼你就需要知道一些功能性的API,在很多流行的神經網絡中,我們都有一個最小的網絡結構,完整的模型是根據這些最小的模型進行疊加完成的。這些基礎的API可以讓你一層一層的構建模型。因此,你只需要很少的代碼就可以來構建一個完整的複雜神經網絡。
讓我們來看看它是如何工作的。首先,你需要導入一些包。
[Python]
現在,你需要去指定輸入數據,而不是在順序模型中,在最後的
fit 函數中輸入數據。這是序列模型和這些功能性的API之間最顯著的區別之一。我們使用
input() 函數來申明一個 1*28*28 的張量。
[Python]
現在,讓我們來利用API設計一個卷積層,我們需要指定要在在哪個層使用卷積網絡,具體代碼這樣操作:
[Python]
最後,我們對於指定的輸入和輸出數據來構建一個模型。
[Python]
當然,我們還需要指定損失函數,優化器等等。但這些和我們在序列模型中的操作一樣,你可以使用
fit 函數和
compile 函數來進行操作。
接下來,讓我們來構建一個vgg-16模型,這是一個很大很「老」的模型,但是由於它的簡潔性,它是一個很好的學習模型。
6.1 使用Keras API開發VGG卷積神經網絡
VGG:
VGG卷積神經網絡是牛津大學在2014年提出來的模型。當這個模型被提出時,由於它的簡潔性和實用性,馬上成爲了當時最流行的卷積神經網絡模型。它在圖像分類和目標檢測任務中都表現出非常好的結果。在2014年的ILSVRC比賽中,
VGG 在Top-5中取得了92.3%的正確率。 該模型有一些變種,其中最受歡迎的當然是 vgg-16,這是一個擁有16層的模型。你可以看到它需要維度是 224*224*3 的輸入數據。
Vgg 16 architecture
讓我們來寫一個獨立的函數來完整實現這個模型。
[Python]
我們可以將這個完整的模型,命名爲 vgg16.py。
在這個例子中,我們來運行
imageNet 數據集中的某一些數據來進行測試。具體代碼如下:
[Python]
正如你在圖中看到的,模型會對圖片中的物體進行一個識別預測。
我們通過API構建了一個VGG模型,但是由於VGG是一個很簡單的模型,所以並沒有完全將API的能力開發出來。接下來,我們通過構建一個 SqueezeNet模型,來展示API的真正能力。
6.2 使用Keras API構建並運行SqueezeNet卷積神經網絡
SequeezeNet 是一個非常了不起的網絡架構,它的顯著點不在於對正確性有多少的提高,而是減少了計算量。當SequeezeNet的正確性和AlexNet接近時,但是ImageNet上面的預訓練模型的存儲量小於5 MB,這對於在現實世界中使用CNN是非常有利的。SqueezeNet模型引入了一個 Fire模型,它由交替的 Squeeze 和 Expand 模塊組成。
SqueezeNet fire module
現在,我們對 fire 模型進行多次複製,從而來構建完整的網絡模型,具體如下:
爲了去構建這個網絡,我們將利用API的功能首先來構建一個單獨的
fire 模塊。
[Python]
純文本查看
複製代碼
[Python]
模塊化處理
[Python]
現在,我們可以利用我們構建好的單獨的 fire 模塊,來構建完整的模型。
[Python]
純文本查看
複製代碼
完整的網絡模型我們放置在 squeezenet.py 文件裏。我們應該先下載 imageNet 預訓練模型,然後在我們自己的數據集上面進行訓練和測試。下面的代碼就是實現了這個功能:
[Python]
純文本查看
複製代碼
|