用 Keras 編寫你的第一個人工神經網絡(Python)—— Jinkey 翻譯

譯者:Jinkey(微信公眾號 jinkey-love)
英文原版地址:點擊跳轉

教程概述

這里不需要編寫太多的代碼,不過我們將一步步慢慢地告訴你怎么以后怎么創建自己的模型。
教程將會涵蓋以下步驟:

  1. 加載數據
  2. 定義模型
  3. 編譯模型
  4. 訓練模型
  5. 評估模型
  6. 結合所有步驟在一起

這個教程的前置條件:

  1. 有 python 2 或 3 的環境和編程基礎
  2. 安裝并配置好 Scipy 庫(包括 Numpy )
  3. 你安裝好 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 函數。曾經 Sigmoidtanh 激活函數是所有的層首選的。但時至今日, 使用 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 個步驟:

  1. 加載數據
  2. 定義模型
  3. 編譯模型
  4. 訓練模型
  5. 評估模型

有任何疑問歡迎關注我的公眾號 jinkey-love 和我交流。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,516評論 2 379

推薦閱讀更多精彩內容