使用 Python 和 Keras 逐步開發你的第一個神經網絡(轉)
原文:Develop Your First Neural Network in Python With Keras Step-By-Step
譯者:飛龍
Keras 是一個功能強大且易於使用的 Python 庫,用於開發和評估深度學習模型。
它包含高效的數值計算庫 Theano 和 TensorFlow,允許你使用幾行代碼定義和訓練神經網絡模型。
在這篇文章中,你將了解如何使用 Keras 和 Python 中創建你的第一個神經網絡模型。
讓我們開始吧。
概覽
我們不需要很多代碼,但我們會慢慢跨過它,以便你將來知道如何創建自己的模型。
本教程中介紹的步驟如下:
- 加載數據
- 定義模型
- 編譯模型
- 擬合模型
- 評估模型
- 把它放在一起
本教程有一些要求:
你已安裝並配置了Python 2 或 3。 你已安裝並配置了 SciPy(包括 NumPy)。 你安裝並配置了 Keras 和后端(Theano 或 TensorFlow)。
如果你需要環境方面的幫助,請參閱教程:
創建一個名為keras_first_network.py
的新文件,然后在前進過程中,將代碼鍵入或復制並粘貼到文件中。
1. 加載數據
每當我們處理使用隨機過程(例如隨機數)的機器學習算法時,最好設置隨機數種子。
這樣你就可以反復運行相同的代碼並獲得相同的結果。如果你需要演示結果,使用相同的隨機源比較算法,或調試代碼的一部分,這非常有用。
你可以使用你喜歡的任何種子初始化隨機數生成器,例如:
from keras.models import Sequential from keras.layers import Dense import numpy # fix random seed for reproducibility numpy.random.seed(7)
現在我們可以加載我們的數據。
在本教程中,我們將使用皮馬印第安人糖尿病數據集。 這是來自 UCI 機器學習庫的標准機器學習數據集。 它描述了皮馬印第安人的患者病歷數據,以及他們是否在五年內患有糖尿病。
因此,它是二元分類問題(糖尿病發作為 1 或沒有為 0)。 描述每個患者的所有輸入變量都是數字的。 這使得它可以直接用於接受數字輸入和輸出值的神經網絡,是我們在 Keras 的第一個神經網絡的理想選擇。
下載數據集並將其放在本地工作目錄中,與 python 文件相同。 使用文件名保存:
pima-indians-diabetes.csv
你現在可以使用 NumPy 函數loadtxt()
直接加載文件。 有八個輸入變量和一個輸出變量(最后一列)。 加載后,我們可以將數據集拆分為輸入變量(X
)和輸出類變量(Y
)。
# load pima indians dataset dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",") # split into input (X) and output (Y) variables X = dataset[:,0:8] Y = dataset[:,8]
我們初始化了隨機數生成器,以確保我們的結果可重現並加載我們的數據。 我們現在准備定義我們的神經網絡模型。
注意,數據集有 9 列,范圍 0:8 將選擇 0 到 7 之間的列,在索引 8 之前停止。如果這對你來說是新的,那么你可以在此博文中了解數組切片和范圍的更多信息:
2. 定義模型
Keras 中的模型被定義為層的序列。
我們創建一個Sequential
(順序)模型並一次添加一個層,直到我們對網絡拓撲感到滿意為止。
要做的第一件事是,確保輸入層具有正確數量的輸入。這可以使用input_dim
參數創建第一個層並為 8 個輸入變量將其設置為 8 來指定。
我們如何知道層數及其類型?
這是一個非常難的問題。我們可以使用啟發式方法,通常通過試錯的過程找到最好的網絡結構。通常,如果有任何幫助,你需要一個足夠大的網絡來捕獲問題的結構。
在此示例中,我們將使用三層的全連接的網絡結構。
全連接層使用Dense
類定義。我們可以在第一個參數中指定層中神經元的數量,在第二個參數中將初始化方法指定為init
,並使用activation
參數指定激活函數。
在這種情況下,我們將網絡權重初始化為小隨機數,它們從均勻分布('uniform'
)生成,在這種情況下介於 0 和 0.05 之間,因為這是 Keras 中的默認均勻權重初始化。對於從高斯分布產生的小隨機數,另一種傳統的備選項是'normal'
。
我們將在前兩層使用整流器('relu'
)激活函數,在輸出層使用sigmoid
函數。過去,所有層都優先選擇sigmoid
和tanh
激活函數。目前,使用整流器激活函數可以獲得更好的性能。我們在輸出層使用sigmoid
來確保我們的網絡輸出介於 0 和 1 之間,並且很容易映射到類為 1 的概率,或者使用默認閾值 0.5 划分到任一類的硬分類。
我們可以通過添加每一層將它們拼湊在一起。第一層有 12 個神經元,需要 8 個輸入變量。第二個隱藏層有 8 個神經元,最后,輸出層有 1 個神經元來預測類別(糖尿病的發病與否)。
# create model model = Sequential() model.add(Dense(12, input_dim=8, activation='relu')) model.add(Dense(8, activation='relu')) model.add(Dense(1, activation='sigmoid'))
3. 編譯模型
既然定義了模型,我們就可以編譯它。
編譯模型使用背后的高效數字庫(所謂的后端),如 Theano 或 TensorFlow。后端自動選擇最佳方式來為表示網絡用於訓練,並使預測能夠在你的硬件上運行,例如 CPU 或 GPU 甚至分布式。
編譯時,我們必須指定訓練網絡時所需的一些其他屬性。記住訓練網絡意味着找到最好的權重集來預測這個問題。
我們必須指定用於評估一組權重的損失函數,用於搜索網絡的不同權重的優化器,以及我們希望在訓練期間收集和報告的任何可選指標。
在這種情況下,我們將使用對數損失,對於二元分類問題,在 Keras 中將其定義為binary_crossentropy
。我們還將使用高效的梯度下降算法adam
,因為它是一個有效的默認值。在《Adam:隨機優化方法》一文中了解 Adam 優化算法的更多信息。
最后,因為它是一個分類問題,我們將收集並報告分類准確率作為指標。
4. 擬合模型
我們已經定義了我們的模型並為高效計算而將其編譯。
現在是時候在一些數據上執行模型了。
我們可以通過調用模型上的fit()
函數來訓練或擬合我們加載的數據模型。
訓練過程將對名為epochs
的數據集進行固定次數的迭代,我們必須使用nepochs
參數指定。 我們還可以設置實例數,它在執行網絡中的權重更新之前求值,稱為批量大小並使用batch_size
參數進行設置。
對於這個問題,我們將進行少量迭代(150)並使用相對較小的批量大小 10。再次,這些可以通過試錯進行選擇。
# Fit the model model.fit(X, Y, epochs=150, batch_size=10)
這在你的 CPU 或 GPU 上工作。
此示例不需要 GPU,但如果你想知道如何在雲中廉價地在 GPU 硬件上運行大型模型,請參閱此博文:
5. 評估模型
我們已經在整個數據集上訓練了神經網絡,我們可以在同一數據集上評估網絡的性能。
這只會讓我們了解我們對數據集建模的好壞(例如訓練准確率),但不知道算法在新數據上的表現如何。 我們這樣做是為了簡化,但理想情況下,你應該將數據分為訓練和測試數據集,以便對模型進行訓練和評估。
你可以使用模型上的evaluate()
函數在訓練數據集上評估模型,並將其傳遞給用於訓練模型的相同輸入和輸出。
這將為每個輸入和輸出對生成預測並收集分數,包括平均損失和你已配置的任何指標,例如准確度。
# evaluate the model scores = model.evaluate(X, Y) print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
6. 把它放在一起
你剛剛看到如何在 Keras 中輕松創建第一個神經網絡模型。
讓我們將它們組合成一個完整的代碼示例。
# Create your first MLP in Keras from keras.models import Sequential from keras.layers import Dense import numpy # fix random seed for reproducibility numpy.random.seed(7) # load pima indians dataset dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",") # split into input (X) and output (Y) variables X = dataset[:,0:8] Y = dataset[:,8] # create model model = Sequential() model.add(Dense(12, input_dim=8, activation='relu')) model.add(Dense(8, activation='relu')) model.add(Dense(1, activation='sigmoid')) # Compile model model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # Fit the model model.fit(X, Y, epochs=150, batch_size=10) # evaluate the model scores = model.evaluate(X, Y) print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
運行此示例,你應該看到 150 個時期中每個時期的消息,每個時期的損失和准確率,然后是訓練數據集上的訓練模型的最終評估。
在我的工作站上執行大約需要 10 秒鍾,它在后端為 Theano 的 CPU 上運行。
...
Epoch 145/150
768/768 [==============================] - 0s - loss: 0.5105 - acc: 0.7396
Epoch 146/150
768/768 [==============================] - 0s - loss: 0.4900 - acc: 0.7591
Epoch 147/150
768/768 [==============================] - 0s - loss: 0.4939 - acc: 0.7565
Epoch 148/150
768/768 [==============================] - 0s - loss: 0.4766 - acc: 0.7773
Epoch 149/150
768/768 [==============================] - 0s - loss: 0.4883 - acc: 0.7591
Epoch 150/150
768/768 [==============================] - 0s - loss: 0.4827 - acc: 0.7656
32/768 [>.............................] - ETA: 0s
acc: 78.26%
注意:如果你嘗試在 IPython 或 Jupyter筆記本中運行此示例,則可能會出錯。 原因是訓練期間的輸出進度條。 你可以通過在對model.fit()
的調用中設置verbose=0
來輕松關閉它們。
請注意,你的模型的技能可能會有所不同。
神經網絡是一種隨機算法,意味着相同數據上的相同算法可以訓練具有不同技能的不同模型。 這是一個特征,而不是一個 bug。 你可以在博文中了解更多相關信息:
我們確實嘗試固定隨機種子,來確保你和我獲得相同的模型,因此得到相同的結果,但這並不總是適用於所有系統。 我在這里寫了更多使用 Keras 模型重現結果的問題。
7. 附加分:做出預測
我被問到的第一個問題是:
在訓練我的模型后,如何使用它來預測新數據?
好問題。
我們可以調整上面的示例並使用它來生成訓練數據集的預測,假裝它是我們以前從未見過的新數據集。
進行預測就像調用model.predict()
一樣簡單。 我們在輸出層使用sigmoid
激活函數,因此預測將在 0 和 1 之間的范圍內。我們可以通過舍入它們輕松地將它們轉換為這個分類任務的清晰二元預測。
下面列出了完整示例,為訓練數據中的每條記錄做出預測。
# Create first network with Keras from keras.models import Sequential from keras.layers import Dense import numpy # fix random seed for reproducibility seed = 7 numpy.random.seed(seed) # load pima indians dataset dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",") # split into input (X) and output (Y) variables X = dataset[:,0:8] Y = dataset[:,8] # create model model = Sequential() model.add(Dense(12, input_dim=8, init='uniform', activation='relu')) model.add(Dense(8, init='uniform', activation='relu')) model.add(Dense(1, init='uniform', activation='sigmoid')) # Compile model model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # Fit the model model.fit(X, Y, epochs=150, batch_size=10, verbose=2) # calculate predictions predictions = model.predict(X) # round predictions rounded = [round(x[0]) for x in predictions] print(rounded)
現在運行此修改示例將打印每個輸入的預測。 如果需要,我們可以直接在我們的應用中使用這些預測。
[1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
如果你對使用經過訓練的模型進行預測有更多疑問,請參閱此博文:
總結
在這篇文章中,你發現了如何使用功能強大的 Keras Python 庫,為深度學習創建你的第一個神經網絡模型。
具體來說,你學習了使用 Keras 創建神經網絡或深度學習模型的五個關鍵步驟,包括:
- 如何加載數據。
- 如何在 Keras 中定義神經網絡。
- 如何使用高效的數值后端編譯 Keras 模型。
- 如何訓練數據模型。
- 如何評估數據模型。