在這篇 Keras 教程中, 你將學到如何用 Python 建立一個卷積神經網絡!
事實上, 我們將利用著名的 MNIST 數據集, 訓練一個準確度超過 99% 的手寫數字分類器.
開始之前, 請注意, 本指南是面向對應用深度學習感興趣的初學者的.
我們旨在向你介紹一個最流行的同時也是功能最強大的, 用於建立神經網絡的 Python 庫. 這意味著我們將跳過許多理論與數學知識, 但我們還是會向你推薦一些學習這些的極好的資源.
本指南推薦的預備知識有:
為了能快速開始, 我們假設你已經具備了這方面的知識.
為什麼要用 Keras?Keras 是我們推薦的 Python 深度學習庫, 尤其是對於初學者而言. 它很簡約, 模塊化的方法使建立並運行神經網絡變得輕巧. 你可以在這裡讀到更多關於 Keras 的內容:
深度學習究竟是什麼?深度學習是指具有多隱層的神經網絡, 其可以學習輸入數據的抽象表示. 這個定義顯然太簡單了, 但對於現在的我們來說, 卻是最有實際意義的.
比方說, 深度學習促進了計算機視覺的巨大進步. 現在, 我們能夠對圖片進行分類, 識別圖片中的物體, 甚至給圖片打標籤. 要實現這些, 多隱層的深度神經網絡可以從原始輸入圖片中按序學習更複雜的特徵:
第一層隱層也許只能學習到局部邊緣模式.
之後, 每一個後續層 (或過濾器) 將學習更複雜的表示.
最後, 最後一層可以對圖片進行分類, 是貓還是袋鼠.
這類深度神經網絡就稱為卷積神經網絡.
卷積神經網絡究竟是什麼?簡而言之, 卷積神經網絡 (CNN) 就是將輸入數據假設成圖的多層神經網絡 (有些時候, 會有多達 17 甚至更多層).
通過實現這個需求, CNN 可以大大減少需要調整的參數數量. 因此, CNN 可以高效處理高維原始圖片.
卷積神經網絡的底層機制已經超過了本教程的範圍, 更多請看這裡.
本教程不是什麼:這不是一門深度學習的完整課程. 相反地, 本教程旨在帶你從零到一, 儘量”無痛”地建立卷積神經網絡!
如果你有興趣掌握深度學習背後的理論, 強烈推薦史丹福大學的這門課:
開始前的小提示:我們試著讓教程儘可能流線化, 這意味著任何一個主題, 我們都不會太深究細節. 萬一你想要學習關於一個函數或模塊更多的知識, 同時打開 Keras 文檔 很有幫助.
Keras 教程目錄下面是創建你的第一個卷積神經網絡 (CNN) 的步驟:
配置環境
安裝 Keras
導入庫和模塊
從 MNIST 導入圖片數據
預處理輸入數據
預處理類標籤
定義模型架構
編譯模型
用訓練數據擬合模型
用測試數據評估模型
第一步: 配置環境首先, 掛一張勵志海報:
可能沒什麼用- -.
然後, 確保你的計算機上已經安裝了以下軟體:
Python 2.7+ (Python 3 也可以, 但總體而言, Python 2.7 在數據科學領域依舊更受歡迎.)
Scipy 和 NumPy
Matplotlib (可選的, 推薦用於探索性分析)
Theano* (安裝指南)
強烈建議使用 Anaconda 發行版 來安裝 Python, NumPy, SciPy. 它自帶所有這些包.
注意: 用 TensorFlow 也可以 (作為 Theano 的替代), 但我們將堅持使用 Theano, 以保持程序足夠簡單. 使用 TensorFlow 和 Theano 的主要區別在於, 數據輸入神經網絡之前, 需要簡單地重塑.
你可以檢查一下是否都正確安裝了:打開命令行窗口 (Mac 上是 Terminal), 並輸入:
你將看到 Python 解釋器:
然後, 可以導入上述庫並列印版本信息:
如果我們沒有涵蓋如何安裝 Keras, 這就不是一篇 Keras 的教程.
好消息是, 如果你使用的 Anaconda, 你已經安裝好了一個超讚的包管理系統: pip.
你可以在命令行輸入 $ pip 確認安裝. 這條命令將列印一個命令和選項的列表. 如果你還沒有安裝 pip, 參照這裡進行安裝.
安裝好 pip 之後, 安裝 Keras 就很簡單了:
同樣地, 你可以確認是否正確安裝:
哎呀, 看起來好像 Keras 版本太低了. 版本升級也很簡單:
完美, 現在就可以開始了, 新建一個 Python 文件, 命名為 keras_cnn_example.py.
首先, 導入 numpy 並設置偽隨機數生成器設置種子. 這允許我們從腳本中重現結果:
然後, 從 Keras 中導入 Sequential 模塊. 它是一個神經網絡層的線性棧, 完美適配本教程將建立的前饋 CNN 類型.
然後, 從 Keras 中導入 “核心” 層. 這些是幾乎所有神經網絡都會用到的層:
接下來, 我們從 Keras 中導入 CNN 層. 這些是卷積層, 將幫助我們有效地訓練圖片數據:
最後, 導入一下工具. 這將為我們之後的數據轉換提供幫助:
現在, 我們有了建立神經網絡架構所需的一切.
MNIST 是深度學習和計算機視覺入門很好的數據集. 它很大, 這對於神經網絡是一個巨大的挑戰, 但它在單臺計算機上又是可管理的. 我們將在另一個文章中對此進行更多的討論: 6 Fun Machine Learning Projects for Beginners.
很方便的是, Keras 庫已經包含了 MNIST. 可以像這樣加載它:
看一下數據集的形狀:
很好, 看來我們的訓練集中有 60000 個樣本, 每張圖片都是 28*28 像素大小的. 我們可以用 matplotlib 繪製第一個樣例進行確認:
輸出的圖片是這樣的:
總的來說, 做計算機視覺的, 在進行任何算法工作之前, 可視地繪製數據很有幫助. 這是一個快速明智的檢查, 可以防止可避免的錯誤 (比如對數據維度的誤解).
在後端使用 Theano 時, 你必須顯式地聲明一個維度, 用於表示輸入圖片的深度. 舉個例子, 一幅帶有 RGB 3 個通道的全彩圖片, 深度為 3.
MNIST 圖片的深度為 1, 因此必須顯式地進行聲明.
換言之, 我們要將數據集從 (n, width, height) 轉換成 (n, depth, width, height).
可以簡單地實現:
可以再次列印 X_train 的維度, 進行確認:
輸入數據最後的預處理步驟是, 將數據類型轉換成 float32, 並且進行標準化, 使值落在 [0, 1] 區間內.
現在, 模型訓練的輸入數據就已經準備好了.
接下來, 讓我們看一下類標籤數據的形狀:
呃…可能有點問題. 我們應該有 10 個不同的類型, 每一個類代表一個數字, 但是看起來, 現在只有一個 1 維數組. 再來看下前 10 個訓練樣本的標籤:
問題依舊. y_train 和 y_test 數據並沒有被分成 10 個不同的類標籤, 而是被表示成一個類型值的單一數組.
對此, 我們可以進行簡單的修正:
再看一眼:
好多了!
現在, 我們就可以定義我們的模型架構了. 在實際研發工作中, 研究員會花大量的時間研究模型架構.
在這裡, 為了教程的繼續, 我們不會討論理論或數學. 這本身就是複雜的領域, 對於想要深入學習的同學, 建議看一下上文提到的 CS231n 課程.
另外, 剛開始時, 你可以使用現成的例子或者實現紫黯學術論文中已經證明的架構. 這裡有一個 Keras 實現樣例.
我們先聲明一個順序模型:
然後, 聲明一個輸入層:
輸的形狀參數應為形狀為 1 的樣例. 本例中, 就是 (1, 28, 28), 與每張數字圖片的 (depth, width, height) 相對應.
但是前 3 個參數又代表什麼呢? 它們分別對應於要使用的卷積過濾器的數量, 每個卷積內核的行數與列數.
注意: 默認情況下, 步長為 (1, 1), 可以用 ‘subsample’ 參數進行調整.
列印當前模型的輸出進行確認:
然後, 我們可以像搭積木一樣向模型中添加更多的層:
再次聲明, 我們不會太深究理論的東西, 但有必要強調一下我們剛剛添加的 Dropout 層. 這是一個規範化模型的方法, 目的是防止過度擬合. 你可以在這裡看到更多內容.
MaxPooling2D 是一種減少模型參數數量的方式, 其通過在前一層上滑動一個 2*2 的濾波器, 再從這個 2*2 的濾波器的 4 個值中取最大值.
到目前為止, 對於模型的參數, 我們已經添加了 2 個卷積層. 要完成模型的架構, 讓我們添加一個完全連接的層和輸出層:
對於 Dense 層, 第一個參數是輸出的大小. Keras 會自動處理層間連接.
注意到最後一層的輸出大小為 10, 對應於 10 個數字類型.
同時還要注意, 卷積層的權重在傳遞給完全連接的 Dense 層之前, 必須壓平 (維度為 1).
以下是完整的模型架構:
現在, 我們唯一需要做的就是定義損失函數和優化器, 然後就可以對模型進行訓練了.
現在可以輕鬆一點了, 最難的部分已經過去了.
只需要編譯模型, 然後我們就可以訓練它了. 編譯模型時, 我們需要聲明損失函數和優化器 (SGD, Adam 等等).
Keras 有各種各樣的 損失函數和開箱即用的優化器.
要擬合模型, 我們需要做的就是聲明訓練的批次大小以及訓練次數, 然後傳入訓練數據.
簡單嗎?
你也可以使用各種回調函數來設置提前結束的規則, 保存模型權重, 或記錄每次訓練的歷史.
第十步: 用測試數據評估模型最後, 可以用測試數據對模型進行評估:
恭喜! 你已經完成了本 Keras 教程.
我們剛剛體驗了 Keras 的核心功能, 但也僅僅是體驗. 希望通過本教程, 你已經獲得了進一步探索 Keras 所有功能的基礎.
如果希望繼續學習, 我們推薦學習其他的 Keras 樣例模型 和史丹福大學的計算機視覺課程.
完整的代碼以下就是本教程的所有代碼, 保存為一個腳本: