[譯] 使用 Python 和 Keras 實現卷積神經網路

JohnJiangLA發表於2018-05-07

你有沒有想過?Snapchat 是如何檢測人臉的?自動駕駛汽車是怎麼知道路在哪裡?你猜的沒錯,他們是使用了卷積神經網路這種專門用於處理計算機視覺的神經網路。在前一篇文章中,我們研究了它們是怎麼工作的。我們討論了這些神經網路的層及其功能。基本上,卷積神經網路的附加層會將影象處理成神經網路能夠支援的標準格式。這樣做的第一步是檢測某些特徵或屬性,這些工作是由卷積層完成的。

這一層使用過濾器來檢測低層次的特徵(比如邊緣和曲線)以及更高層次的特徵(比如臉和手)。然後卷積神經網路使用附加層消除影象中的線性干擾,這些干擾會導致過分擬合。當線性干擾移除後,附加層會將影象下采樣並將資料進行降維。最後,這些資訊會被傳遞到一個神經網路中,在卷積神經網路中它叫全連線層。同樣,本文的目標是如何實現這些層,因此關於這些附加層的更多細節以及如何工作和具體用途都可以在前一篇文章中找到。

[譯] 使用 Python 和 Keras 實現卷積神經網路

在我們開始解決問題和開始碼程式碼之前,請正確配置好你的環境。與本系列之前的所有文章一樣,我會使用 Python 3.6。另外,我使用的是 Anaconda 和 Spyder,但是你也可以使用其他的 IDE。然後,最重要的是安裝 Tensorflow 和 Keras。安裝和使用 Tensorflow 的說明請檢視此處,而安裝和使用 Keras 的說明請檢視此處

MNIST 資料集

因此,在本文中,我們將訓練我們的網路來識別影象中的數字。為此,我們將使用另一個著名的資料集 —— MNIST 資料集。在前身 NIST 的基礎上,這個資料集由一個包含 60,000 個樣本的訓練集和一個包含 10,000 個手寫數字影象的測試集組成。所有數字都已大小歸一化並居中了。影象的大小也是固定的,因此預處理影象資料已被最簡化了。這也是這個資料集為何如此流行的原因。它被認為是卷積神經網路世界中的 “Hello World” 樣例。

[譯] 使用 Python 和 Keras 實現卷積神經網路

MNIST 資料集樣例

此外,使用卷積神經網路,我們可以得到與人類判斷相差無幾的結果。目前,這一紀錄由 Parallel Computing Center(赫梅爾尼茨基,烏克蘭)保持。他們只使用了由 5 個卷積神經網路組成的集合,並將錯誤率控制在 0.21%。很酷吧?

匯入庫和資料

本系列前面的文章一樣,我們首先匯入所有必要的庫。其中一些是我們熟悉的,但是其中一些需要進一步講解。

正如你所見,我們將使用 numpy,這是我們在前面的示例中用於操作多維陣列和矩陣的庫。另外,也可以看到,我們會使用一些本系列之前 Keras 庫中用過的特性,也會使用一些新特性。比如建立模型和標準層(比如全連線層)會使用到 SequentialDense

此外,我們還會使用一些 Keras 中的新類。Conv2D 是用於建立卷積層的類。MaxPooling2D 則是用於建立池化層的類,而 Flatten 是用於降維的類。我們也使用 Keras util 中的 to_categorical。該類用於將向量(整形量)轉化為二值類別矩陣,即它用於 one-hot 編碼。最後,注意我們將使用 matplotlib 來顯示結果。

匯入必要的庫和類之後,我們需要處理資料。幸運的是,Keras 提供了 MNIST 資料集, 所以我們不需要下載它。如前所述,所有這些影象都已經進行了部分預處理。這意味著他們有相同的大小和數字位於合適的位置。因此,讓我們匯入這個資料集併為我們的模型準備資料:

如你所見,我們從 Keras 資料集中匯入了 MNIST 資料集。然後,我們將資料載入到訓練和測試矩陣中。在此基礎上,利用形狀屬性得到影象的維數,並對輸入資料進行重構,從而得到輸入影象的一個通道。基本上,我們只使用這個影象的一個通道,而不是常規的三個通道(RGB)。這樣做是為了簡化實現的難度。然後對輸入矩陣中的資料進行歸一化處理。最後,我們使用 to_categorical 對輸出矩陣進行編碼。

模型建立

現在,資料已經準備好了,我們可以開始最有趣的環節了 —— 建立模型:

理所當然的,我們為此需要使用 Sequential,並首先使用 Conv2D 類新增摺積層。正如你所見的,這個類使用的引數很少,所以讓我們一起來研究下。第一個引數是定要使用的過濾器個數,即要檢測的特徵個數。通常來說我們從 32 開始隨後逐步增大這個數字。這正是我們在做的,在第一個卷積層中我們檢測 32 個特徵,第二層中 64 個,最後的第三層中 128 個。使用的過濾器大小則由下一個引數 —— kernel_size 來定義,我們已經選擇了 3*3 的過濾器。

在啟用函式中,我們使用整流器函式。這樣,在每個卷積層中非線性程度都會自然增加。實現這一點的另一種方法是使用 keras.layers.advanced_activations 中的 LeakyReLU。它不像標準的整理器函式,不是將所有低於某一固定值的值壓縮為零,而是有一個輕微的負斜率。如果你決定使用它,請注意必須使用 Conv2D 中的線性啟用。下面就是這種方式的樣例:

我們有點跑題了。講回到 Conv2D 及其引數。另一個非常重要的引數是 input_shape。使用這個引數,定義輸入影象的維數。如前所述,我們只使用一個通道,這是為什麼我們的 input_shape 最終維度是 1。這是我們從輸入影象中提取的維度。

此外,我們還在模型中新增了其它層。Dropout 層能幫助我們防止過分擬合,此後,我們使用 MasPooling2D 類新增池化層。顯然,這一層使用的是 max-pool 演算法,池化過濾器的大小則是 2*2。池化層之後是降維層,最後是全連線層。對於最後的全連線層,我們新增了兩層的神經網路,對於這兩層,我們使用了 Dense 類。最後,我們編譯模型,並使用了 Adam 優化器。

如果你不明白其中的一些概念,你可以檢視之前的文章,其中解釋了卷積層的原理機制。另外,如果你對於一些 Keras 的內容有疑惑,那麼這篇文章會幫助到你。

訓練

很好,我們的資料預處理了,我們的模型也建好了。下面我們將他們合併到一起,並訓練我們的模型。為了使我們正在使用的能夠運轉正常。我們傳入輸入矩陣並定義 batch_sizeepoch 數。我們要做的另外一件事是定義 validation_split。這個引數用於定義將測試資料的哪個部分用作驗證資料。

基本上,該模型將保留部分訓練資料,但它使用這部分資料在每個迴圈結束時計算損失和其他模型矩陣。這與測試資料不同,因為我們在每個迴圈結束後都會使用它。

在我們的模型已經訓練完成並準備好之後,我們使用 evaluate 方法並將測試集傳入。這裡我們能夠得出這個卷積神經網路的準確率。

預測

我們可以做的另一件事是在測試資料集中收集對對神經網路的預測。這樣,我們就可以將預測結果和實際結果進行比較。為此,我們將使用 predict 方法。使用這個方法我們還可以對單個輸入進行預測。

結果

讓我們使用這些我們剛剛收集到的預測來完成我們實現的最後一步。我們將顯示預測的數字與實際的數字。我們還會顯示我們預測的影象。基本上,我們將為我們的實現做很好的視覺化展示。畢竟,我們在處理影象。

在這裡,我們使用了 pyplot 來顯示十幅影象,並給出了實際結果和我們的預測。當我們執行我們的實現時,如下圖所示:

[譯] 使用 Python 和 Keras 實現卷積神經網路

我們執行了 20 輪並得到了 99.39% 的準確率。並不差,當然這還有提升空間。

結論

卷積神經網路是計算機視覺領域中一個非常有趣的分支,也是最有影響力的創新之一。本文中我們實現了這些神經網路中的一個簡易版本並用它來檢測 MNIST 資料集上的數字。

感謝閱讀!


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章