譯者:Jinkey(微信公眾號 jinkey-love)
英文原版地址:點擊跳轉
教程概述
這里不需要編寫太多的代碼,不過我們將一步步慢慢地告訴你怎么以后怎么創建自己的模型。
教程將會涵蓋以下步驟:
- 加載數據
- 定義模型
- 編譯模型
- 訓練模型
- 評估模型
- 結合所有步驟在一起
這個教程的前置條件:
- 有 python 2 或 3 的環境和編程基礎
- 安裝并配置好 Scipy 庫(包括 Numpy )
- 你安裝好 Keras 并且有一個后端(Theano or TensorFlow)
創建一個新的文件,命名為 keras_first_network.py ,然后將教程的代碼一步步復制進去。
1. 加載數據
每當我們使用機器學習算法使用隨機過程(如隨機數),先設置隨機數種子是一個好的習慣。
這樣您就可以運行相同的代碼一次又一次,得到相同的結果。如果你需要證明結果,使用隨機數據比較算法或調試代碼,這是很有用的。
你可以初始化隨機數發生器及其種子,例如:
from keras.models import Sequential
from keras.layers import Dense
import numpy
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
現在我們可以加載我們的數據了。
在這個教程中,我們將使用皮馬印第安人糖尿病數據集.這是UCI 機器學習數據庫一個標準的機器學習數據集。它描述了病人醫療記錄和他們是否在五年內發病。
因此,它是一個二分類問題(出現糖尿病為1, 否則為 0)。
所有描述病人的輸入變量都是數值。這便于直接用于需要數值輸入輸出的神經網絡, 適合我們第一個 Keras 神經網絡。
下載數據集并且重命名為 pima-indians-diabetes.csv
放入 python 腳本所在的目錄的 data/pima-indians-diabetes.csv
。
你可以只直接使用 Numpy 庫的 loadtxt()
方法加載數據,一共 8 個輸出變量和 1 個輸出變量(最后一列)。加載之后我們就可以把數據分離為 X(輸出變量)和 Y(輸出分類)
# load pima indians dataset
dataset = numpy.loadtxt("data/pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:, 0:8]
Y = dataset[:, 8]
我們已經初始化了我們對的隨機數生成器來確保結果可復現, 也加載了數據。我們現在可以準備定義我們的神經網絡模型了。
2. 定義模型
Keras 中的模型被定義為一系列的層。
我們實例化一個 Sequential 模型對象,每次添加一層知道我們對網絡的拓撲結構滿意。
第一件事情我們需要確保的是輸出神經元的數量。這可以在模型創建的時候設置參數 input_dim 來定義,我們將這個參數設置為 8 對應 8 個輸出變量。
我們怎么知道層的數量和他們的類型呢?
這是一個非常難回答的問題。這是啟發式的,我們通過不斷地試錯找出最好的網絡結構、一般來說,你需要足夠大的網絡去明白結構對于問題是否有用。
在這個例子中, 我們使用三層全連接的結構。
全連接層使用 Dense 定義。我們可以通過第一個參數定義層的神經元數量,第二個參數 init 定義權重的初始化方法, activation 參數定義激活函數。
在這個例子中, 我們把權重初始化成一個服從均勻分布的小隨機數(init='uniform'
),在0到0.05直接(這是 Keras 標準均勻分布權重初始值)。另一種傳統的選擇是‘normal’
,會從高斯分布(正態分布)中產生一個小的隨機數。
我們在前兩層使用 (relu)[https://en.wikipedia.org/wiki/Rectifier_(neural_networks)] 激活函數, 在輸出層使用 Sigmoid
函數。曾經 Sigmoid
和 tanh
激活函數是所有的層首選的。但時至今日, 使用 relu 激活函數可以達到更好的性能。我們在輸出層使用 Sigmoid 函數來確保網絡輸出在 0 和 1 之間,
我們可以添加每一層將這些東西放到一起。第一層有 12 個神經元、8個輸出變量。第二層有 8 個神經元和最后 1 個神經元的輸出層用于預測類別(糖尿病有無發病)
# 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'))
3. 編譯模型
現在我們定義好模型, 那么就可以編譯他了。
編譯使用高效的數學庫, 封裝了 Theano 或者 TensorFlow(稱為 backend)。后端(backend)在你的硬件上自動選擇最好的方式去表現用于訓練和預測的神經網絡,比如 CPU、GPU 或者分布式。
編譯時, 我們需要額外定義訓練網絡所需要的參數。記住, 訓練網絡意味著尋找最優的權重集去預測。
我們需要定義評估權重集的損失函數, 用于尋找不同權重的優化器以及我們希望在訓練過程呈現的可選指標。
在這個例子中, 我們使用對數損失函數(logarithmic loss), 對于二分類問題, 其在 Keras 中稱為“binary_crossentropy”。我們還將使用梯度下降算法‘adam’, 沒有為什么, 它就是一種高效地默認方法。想了解更多這種算法可以查看論文: (Adam: A Method for Stochastic Optimization)[http://arxiv.org/abs/1412.6980]
最后, 以為這是一個分類問題, 所以我們會收集和匯報分類的準確率作為度量指標。
# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
4. 訓練模型
我們已經定義和編譯了模型, 他是為高效地計算而準備的。
現在是時候在數據上訓練模型了。
我們可以在加載的數據上訓練和擬合模型,通過 fit() 函數。
訓練過程會在數據集迭代一定的次數,成為 epochs, 這個可以通過 nb_epoch
參數來設定。我們也可以設定 batch_size
參數來指定進行梯度下降時每個batch包含的樣本數。訓練時一個batch的樣本會被計算一次梯度下降, 使目標函數優化一步。在這個例子中, 我們將迭代150次、批處理大小為10。再說一次, 這些參數可以通過試錯來選擇。
# Fit the model
model.fit(X, Y, nb_epoch=150, batch_size=10)
這就是在你的 CPU 或者 GPU 上發生的事情。
5. 評估模型
我們已經在整個數據集上訓練了我們的神經網絡, 我們可以在線通的數據集上評估神經網絡的性能。
這只會告訴我們模型有多適合已有的數據(訓練的準確率),但我們無從知道算法在新數據上的性能。
我們可以簡單但很理想地把數據分為訓練集和測試集來分別訓練和評估模型。
你可以通過 evaluate()
函數在訓練集評估你的模型, 使用你訓練模型時相同的輸出和輸出。
這會針對每一個輸出-輸出產生預測并且收集分數,包括平均損失和其他我們定義的指標,比如準確率。
# evaluate the model
scores = model.evaluate(X, Y)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
6. 將這些放在一起
你已經看到用 Keras 創建你的第一個神經網絡有多么簡單、
運行以上的代碼, 將會看到150個迭代中, 每次迭代的損失和準確率,以及最終的模型在訓練集上的評估結果, 在我的 CPU 上耗時 10s(使用 Theano 作為后端)
...
Epoch 143/150
768/768 [==============================] - 0s - loss: 0.4614 - acc: 0.7878
Epoch 144/150
768/768 [==============================] - 0s - loss: 0.4508 - acc: 0.7969
Epoch 145/150
768/768 [==============================] - 0s - loss: 0.4580 - acc: 0.7747
Epoch 146/150
768/768 [==============================] - 0s - loss: 0.4627 - acc: 0.7812
Epoch 147/150
768/768 [==============================] - 0s - loss: 0.4531 - acc: 0.7943
Epoch 148/150
768/768 [==============================] - 0s - loss: 0.4656 - acc: 0.7734
Epoch 149/150
768/768 [==============================] - 0s - loss: 0.4566 - acc: 0.7839
Epoch 150/150
768/768 [==============================] - 0s - loss: 0.4593 - acc: 0.7839
768/768 [==============================] - 0s
acc: 79.56%
如果你嘗試在 IPython 或者 Jupyter , 你將會得到錯誤。原因是在訓練期間輸出進度條。你可以關閉這個, 通過讓 model.fit()
的參數 verbose=0
福利: 做出預測
我被問得最多的一個問題是:
在我訓練模型之后, 怎么預測新數據的分類?
這是個好問題。
我們擬合了上述例子, 用他來在訓練集上作出預測, 假裝我們之前沒看到過這些數據。
做預測同樣非常簡單, 只需要使用 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, nb_epoch=150, batch_size=10, verbose=2)
# calculate predictions
predictions = model.predict(X)
# round predictions
rounded = [round(x) 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 創建自己的第一個神經網絡模型。
特別是我們學會了 使用 Keras 來創建神經網絡或深度學習模型時關鍵的 5 個步驟:
- 加載數據
- 定義模型
- 編譯模型
- 訓練模型
- 評估模型
有任何疑問歡迎關注我的公眾號 jinkey-love 和我交流。