閱讀232 返回首頁    go 阿裏雲 go 技術社區[雲棲]


用“Keras”11行代碼構建CNN

更多深度文章,請關注:https://yq.aliyun.com/cloud


2313aaebd15b092de9f7bc81acc99b1b9b16ef0f

我曾經演示過如何使用TensorFlow創建卷積神經網絡(CNN)來對MNIST手寫數字數據集進行分類。TensorFlow是一款精湛的工具,具有強大的功能和靈活性。然而,對於快速原型製作工作,可能顯得有些麻煩。Keras是一個運行在TensorFlow或者Theano的更高級別的庫,旨在流線化構建深度學習網絡的過程。事實上,在上一篇TensorFlow教程中  TensorFlow大約需要42行完成的內容,在Keras中隻需11行就可以完成類似的功能。接下來我將向你展示如何通過Keras做到這一點。

Keras教程將向你展示如何使用MNIST數據集構建CNN並實現> 99%的準確性。它與我之前的卷積神經網絡教程中構建的結構完全相同 ,下圖顯示了網絡的架構:

686925deffd36e353234b696812797bd9429a56b

這個Keras教程的完整代碼可以在這裏找到。

Keras教程中的主要代碼講解:

下麵的代碼是在此Keras教程中使用的CNN結構的膽量

model = Sequential()
model.add(Conv2D(32, kernel_size=(5, 5), strides=(1, 1),
                 activation='relu',
                 input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Conv2D(64, (5, 5), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(1000, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))

接下來我們一步一步的來解釋:

Model  =  Sequential()

Keras中的模型可以有兩種——序貫和通過API函數。對於構建的大多數深度學習網絡,序貫模型是最常用的。它允許你從輸入到輸出整個過程都能輕鬆地堆疊網絡層(甚至循環層)。而API函數可以幫助你構建更複雜的網絡體係結構,本教程將不介紹它。

第一行將模型類型聲明為Sequential()。

model.add(Conv2D(32, kernel_size=(5, 5), strides=(1, 1),
                 activation='relu',
                 input_shape=input_shape))

接下來,我們添加一個2D卷積層來處理2D MNIST輸入的圖像。傳遞給Conv2D()  函數的第一個參數是輸出通道的數量。這裏我們設置為我們有32個輸出通道,下一個輸入是kernel_size,我們選擇了一個5×5移動窗口,其次是xy方向(1,1)的步態。接著,激活函數是整流線性單元,最後我們必須與輸入層的大小提供模型。

還要注意,我們不必聲明任何權重或偏差變量,Keras會幫助我們進行完成。

model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))

接下來我們添加一個2D max pooling層。層的定義很簡單。在這種情況下,我們隻是簡單地指定在xy方向上的池的大小 和(22)的步。

model.add(Conv2D(64, (5, 5), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

接下來,我們添加另一個卷積層+最大池化層,具有64個輸出通道。在KerasConv2D()函數的參數默認的步伐是(1,1),在Keras 中默認步伐是使它等於池的大小。

該層的輸入張量是(batch_size28,28,3228×28是圖像的大小,32是來自上一層的輸出通道數。但是,我們不必明確說明輸入的形狀是什麼,Keras也能自動識別。這樣可以快速組合網絡架構,而不用擔心網絡周圍張量的大小。

model.add(Flatten())
model.add(Dense(1000, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))

現在我們已經在Keras中構建了卷積層,我們希望將這些輸出平坦化,以完全進入我們的連接層。在TensorFlow中,我們為了平坦化必須弄清楚卷積層的輸出張量的大小,還要明確我們的權重和偏差變量的大小。

接下來的兩行聲明了我們的完全連接層,使用Keras中的Dense()層。首先我們指定大小,根據我們的架構,我們指定了1000個節點,每個節點都是由ReLU功能激活。第二個是我們softmax分類或輸出層,這是我們類數量的大小。就這樣 - 我們已經成功地開發了CNN的架構,隻有8行代碼。現在讓我們來訓練模型並執行預測。

訓練和評估卷積神經網絡

我們已經開發了KerasCNN架構,但是我們還沒有指定損失函數,或者告訴框架使用哪種類型的優化器(即梯度下降Adam optimiser等)。在Keras中,這些可以在一個命令中執行:

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.SGD(lr=0.01),
              metrics=['accuracy'])

Keras提供了許多損失函數(或者你可以建立自己的),這裏可以看到的keras所有的損失函數。我們將使用標準交叉熵來進行分類(keras.losses.categorical_crossentropy)。Keras還提供了許多優化器,可以在這裏看到。在這種情況下,我們使用Adam優化器(keras.optimizers.Adam)。最後,我們可以在模型上運行evaluate()時計算的度量。

接下來,我們要訓練我們的模型。這可以通過在Keras中再次運行下麵這個命令來完成:

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test),
          callbacks=[history])

該命令看起來類似於非常受歡迎的Python機器學習庫中scikit learn 使用的語法。我們首先傳遞我們的所有訓練的數據,x_trainy_train,下一個參數是批量大小,我們不必在Keras訓練期間明確我們數據的批量處理,而是指定批量大小。在這種情況下,我們使用的批量大小為128。接下來我們設置訓練周期(在這種情況下為10)。詳細標誌在此處設置為1,指定設定是否要在控製台中打印詳細信息以了解訓練進度。

3328/60000 [>.............................] - ETA: 87s - loss: 0.2180 - acc: 0.9336
3456/60000 [>.............................] - ETA: 87s - loss: 0.2158 - acc: 0.9349
3584/60000 [>.............................] - ETA: 87s - loss: 0.2145 - acc: 0.9350
3712/60000 [>.............................] - ETA: 86s - loss: 0.2150 - acc: 0.9348

最後,我們將驗證或測試數據傳遞給擬合函數,因此Keras知道在模型上運行evaluate()時,會測量指標的數據。

一旦模型被訓練,我們可以評估它並打印結果:

score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

在上述模型培訓10個周期之後,我們實現了99.2%的準確度,你可以看到每個周期的準確性的改善如下圖所示:

faa312dce82274d3fb900c0dbf3bbb62895fed2f

Kersa讓事情很更加簡單了,你不覺得嗎?我希望這個Keras教程已經展示了它如何成為深度學習解決方案的有用框架。

作為一種附錄,我會告訴你如何跟蹤我們通過訓練時期的準確性,這使我能夠生成上麵的圖表。

在Keras中記錄網絡性能

Keras有一個實用的程序,名為回調,可用於跟蹤訓練期間的各種變量。你還可以使用它來創建檢查點,將模型在訓練的不同階段進行保存,以幫助你避免工作結果丟失。整個結果會被傳遞到.fit()函數,如上所述。我會向你顯示一個相當簡單的用例,其中記錄了準確性。

要創建一個回調,我們創建一個繼承的類,它繼承自keras.callbacks.Callback

class AccuracyHistory(keras.callbacks.Callback):
    def   on_train_begin(self, logs={}):
        self.acc = []
    def  on_epoch_end(self, batch, logs={}):
        self.acc.append(logs.get('acc'))

上麵代碼繼承的Callback超類有一些可以在我們的回調定義中覆蓋的方法,例如  on_train_beginon_epoch_endon_batch_beginon_batch_end這些方法的名稱就是代表了訓練過程中我們可以做事情的時刻。在上麵的代碼中,在訓練開始時,我們初始化一個列表self.acc = []來存儲我們的精度結果。使用on_epoch_end ()方法,我們可以從日誌中提取我們想要的變量這是一個字典,默認情況下保留了訓練過程中的丟失和準確性。然後我們實例化這樣的回調:

history = AccuracyHistory()

現在我們可以使用回調參數名將曆史記錄傳遞給.fit()函數。請注意,.fit()需要一個回調參數的列表,所以你必須傳遞這樣的曆史[history]。要訪問我們在訓練完成後創建的準確性列表,你可以簡單地調用history.acc

plt.plot(range(1,11), history.acc)
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.show()

本文由@阿裏雲雲棲社區組織翻譯。

文章原標題《Keras tutorial – build a convolutional neural network in 11 lines》

作者:譯者:袁虎 審閱:

文章為簡譯,更為詳細的內容,請查看原文


最後更新:2017-08-18 11:02:45

  上一篇:go  提高 Java 代碼性能的各種技巧
  下一篇:go  (OpenCV/Python)實現OCR銀行票據