人人都能懂的機器學習——用Keras搭建人工神經(jīng)網(wǎng)絡(luò)06

編譯模型

在創(chuàng)建了模型之后,我們必須要使用compile()方法來指定損失方程和優(yōu)化器像屋。另外齿尽,你還可以指定在訓練和評估過程中計算出一系列其他的指標(作為一個列表輸入):

model.compile(loss="sparse_categorical_crossentropy",
              optimizer="sgd",
              metrics=["accuracy"])

這里使用下面的代碼也能達到完全一樣的效果:

model.compile(loss=keras.losses.sparse_categorical_crossentropy,
              optimizer=keras.optimizers.SGD(),
              metrics=[keras.metrics.sparse_categorical_accuracy])

未來我們還將使用更多其他的損失,優(yōu)化器和指標南用,如果想看一下完整的列表跳芳,可以訪問下面的網(wǎng)址:

https://keras.io/losses/

https://keras.io/optimizers/

https://keras.io/metrics/

我們來簡單解釋一下上面的代碼,首先竹勉,使用sparse_categorical_crossentropy損失函數(shù)是因為我們有離散的標簽(對于每個實例飞盆,只有一個目標類別,在這個模型中就是0到9),并且類別與類別之間是互斥的吓歇。如果我們對每個實例對每個類別都輸出一個概率(就像一位有效編碼one-hot vector一樣孽水,[0., 0., 0., 1., 0., 0.]表示3類別),那我們就用categorical_crossentropy損失就可以了城看。如果需要做二元分類(可能只有一個或者多個二元標簽)女气,那就使用sigmoid函數(shù),而不是softmax激活函數(shù)测柠,同時我們使用binary_crossentropy損失炼鞠。

如果你想將離散的標簽轉(zhuǎn)換成one-hot vector使用keras.utils.to_categorical()函數(shù)。

至于優(yōu)化器轰胁,sgd代表我們使用隨機梯度下降法(Stochastic Gradient Descent)來訓練模型谒主。換句話說,Keras會執(zhí)行之前的文章中所描述的反向傳播算法赃阀。我們未來還會介紹更多高效的優(yōu)化器(它們優(yōu)化了梯度下降的方法霎肯,而并不是自動微分)。使用SGD優(yōu)化器的時候榛斯,調(diào)整學習速度是十分重要的观游。所以一般會使用:

optimizer=keras.optimizers.SGD(lr=XXXXXX)

因為sgd的默認學習速度為0.01。

最后驮俗,既然這是一個分類器懂缕,那么衡量它的準確度accuracy是很有用的。

訓練與評估模型

現(xiàn)在我們的模型已經(jīng)準備好訓練了意述,我們只需調(diào)用fit()方法就可以了:

>>> history = model.fit(X_train, y_train, epochs=30,
... validation_data=(X_valid, y_valid))
...
Train on 55000 samples, validate on 5000 samples
Epoch 1/30
55000/55000 [======] - 3s 49us/sample - loss: 0.7218 - accuracy: 0.7660
- val_loss: 0.4973 - val_accuracy: 0.8366
Epoch 2/30
55000/55000 [======] - 2s 45us/sample - loss: 0.4840 - accuracy: 0.8327
- val_loss: 0.4456 - val_accuracy: 0.8480
[...]
Epoch 30/30
55000/55000 [======] - 3s 53us/sample - loss: 0.2252 - accuracy: 0.9192
- val_loss: 0.2999 - val_accuracy: 0.8926

我們輸入了特性(X_train)和目標類別(y_train)提佣,以及要訓練的epoch次數(shù)(不然的話epoch默認為1,這肯定無法收斂至一個好的結(jié)果)荤崇。所謂epoch就是使用訓練集中的全部數(shù)據(jù)對模型進行一次完整的訓練拌屏,稱為'一代訓練'。不過這個中文叫法實在拗口术荤,不如還是叫一個epoch倚喂。我們還輸入了一個驗證集(這是可選的)。Keras將在每個epoch結(jié)束時度量這些損失和其他指標瓣戚,這對于查看模型的實際執(zhí)行情況非常有用端圈。如果模型在訓練集上的表現(xiàn)比驗證集上的表現(xiàn)好得多,那么模型可能對訓練集進行了過擬合(或者可能存在bug子库,比如說訓練集和驗證集之間的數(shù)據(jù)不匹配)舱权。

這樣就可以了,我們模型已經(jīng)訓練好了仑嗅!如果訓練集和驗證集的數(shù)據(jù)不匹配預期的輸入形狀的話宴倍,就會得到一個異常张症。這可能是最常見的錯誤,我們應(yīng)該熟悉這個異常提示鸵贬,比如:如果嘗試使用一個包含扁平圖像的向量俗他,X_train.reshape(-1,784)。那么就會得到這樣的異常提醒:“ValueError: Error when checking input: expected flatten_input to have 3 dimensions, but got array with shape (60000, 784)”阔逼。

在訓練過程中的每一個epoch兆衅,Keras都會展示已經(jīng)處理的實例數(shù),以及一個處理進度條嗜浮,每個實例訓練的平均時間以及訓練集和驗證集的損失和準確度(或者還有其他設(shè)置好的指標)羡亩。你會看到訓練損失下降了(這是個好現(xiàn)象),在30個epoch之后周伦,驗證集的準確度達到了89.26%夕春,與訓練集的準確度沒有差距太大,所以看起來沒有太大的過擬合發(fā)生专挪。

上面的代碼使用validation_data參數(shù)輸入驗證集及志,我們還可以使用validation_split的方式,設(shè)置一定比例的訓練集用于驗證集寨腔。比如速侈,validation_split=0.1那么Keras將會使用最后10%的數(shù)據(jù)(在打亂順序之前)用于驗證。

如果訓練集很不平衡迫卢,有些類別的實例過多而有些過少倚搬,那么應(yīng)該在fit()方法中設(shè)置class_weight參數(shù),這個參數(shù)會給實例較少的類別更大的權(quán)重乾蛤,給實例過多的類別較小的權(quán)重每界。Keras將會在計算損失時考慮這些權(quán)重。如果需要設(shè)置每個實例的權(quán)重家卖,可以設(shè)置sample_weight參數(shù)(它會取代class_weight)眨层。如果有些實例是由專家標記的,而其他實例是使用公共數(shù)據(jù)平臺標記的上荡,那么每個實例的權(quán)重可能會很有用:你可能希望給專家標記的數(shù)據(jù)更多的權(quán)重趴樱。你也可以在validation_data的tuple中添加第三項,來給驗證集設(shè)置實例權(quán)重酪捡。

fit()方法會返回一個History對象叁征,這個對象包含訓練參數(shù)(history.params),訓練經(jīng)過的epoch(history.history)以及最重要的逛薇,在每個epoch結(jié)束的時候?qū)τ柧毤万炞C集度量的損失和其他指標的結(jié)果字典(history.history)捺疼。如果你用字典創(chuàng)建了Pandas的DataFrame,并且調(diào)用plot()方法永罚,那么就會得到圖1.12:

import pandas as pd
import matplotlib.pyplot as plt
pd.DataFrame(history.history).plot(figsize=(8, 5))
plt.grid(True)
plt.gca().set_ylim(0, 1) # set the vertical range to [0-1]
plt.show()
圖1.12 學習曲線:每個epoch的平均訓練損失和準確度啤呼,每個epoch結(jié)束時的平均驗證損失和準確度.jpg

可以看到议薪,在訓練過程中,訓練準確度和驗證準確度都在穩(wěn)步提高媳友,而訓練損失和驗證損失都在減少。此外产捞,驗證曲線與訓練曲線接近醇锚,這意味著沒有太多的過擬合。在這個例子當中坯临,在訓練剛開始時模型在驗證集上的表現(xiàn)似乎比訓練集上要好焊唬。但事實并非如此:實際上,驗證錯誤是在每個epoch結(jié)束時計算的看靠,而訓練錯誤是在每個epoch期間使用平均值計算的赶促。所以訓練曲線應(yīng)該向左移動半個epoch。這樣挟炬,你就可以發(fā)現(xiàn)訓練和驗證曲線在訓練開始時幾乎完全重合鸥滨。

其實在繪制訓練曲線時,也應(yīng)當將其向左移動半個epoch谤祖。

通常情況下婿滓,如果訓練時間足夠長,訓練集的表現(xiàn)最終會超過驗證集的表現(xiàn)粥喜⊥怪鳎可以看出這個例子當中,模型還沒有完全收斂额湘,驗證損失仍然在下降卿吐,所以你應(yīng)該繼續(xù)訓練。這與再次調(diào)用fit()方法一樣簡單锋华,因為Keras會在它停止的地方繼續(xù)進行訓練(最終應(yīng)該能夠達到接近89%的驗證準確度)嗡官。

如果對模型的表現(xiàn)不滿意,那么應(yīng)該重新調(diào)整超參數(shù)供置。首先要檢查的是學習率谨湘。如果沒什么用,嘗試換一個優(yōu)化器(并總是在更改任何超參數(shù)后重新調(diào)整學習率)芥丧。如果表現(xiàn)仍然不是很好紧阔,那么可以嘗試調(diào)整模型的超參數(shù),例如層的數(shù)量续担、每層神經(jīng)元的數(shù)量以及每個隱藏層使用的激活函數(shù)擅耽。你還可以嘗試調(diào)整其他超參數(shù),比如批處理大形镉觥(可以在fit()方法中使用batch_size參數(shù)進行設(shè)置乖仇,默認值為32)憾儒。我們將在未來的文章當中再次講到超參數(shù)調(diào)優(yōu)。一旦您對模型的驗證準確度感到滿意乃沙,就應(yīng)該在測試集上對其進行評估起趾,以在將模型部署到生產(chǎn)環(huán)境之前估計泛化誤差。使用evaluate()方法就可以評估測試集的準確度了(它還支持其他參數(shù)警儒,比如batch_size以及sample_weight等):

>>> model.evaluate(X_test, y_test)
10000/10000 [==========] - 0s 29us/sample - loss: 0.3340 - accuracy: 0.8851
[0.3339798209667206, 0.8851]

通常模型在測試集中的表現(xiàn)要比驗證集中略差一些训裆,這是很正常的。因為超參數(shù)是根據(jù)驗證集的表現(xiàn)來調(diào)整的(不過在這個例子里我們沒有做任何超參的調(diào)整蜀铲,所以準確度低只是運氣不好)边琉。記住,一定要抵制在測試集中調(diào)超參的誘惑记劝,否則你會對泛化誤差的估計過于樂觀变姨。

使用模型進行預測

接下來,我們可以使用模型的predict()方法對新的實例進行預測了厌丑。這里我們用測試集的前三個實例進行預測:

>>> X_new = X_test[:3]
>>> y_proba = model.predict(X_new)
>>> y_proba.round(2)
array([[0. , 0. , 0. , 0. , 0. , 0.03, 0. , 0.01, 0. , 0.96],
[0. , 0. , 0.98, 0. , 0.02, 0. , 0. , 0. , 0. , 0. ],
[0. , 1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ]],
dtype=float32)

對于每個實例定欧,模型對每個類別都生成了一個概率。例如蹄衷,對于第一個圖像忧额,它估計類別9(短靴)的概率是96%,類別5(涼鞋)的概率是3%愧口,類別7(運動鞋)是1%睦番,其他類別的概率忽略不計。

換句話說耍属,模型“相信”第一個圖片是鞋類托嚣,最有可能是短靴,但也不完全確定厚骗,可能是涼鞋或運動鞋示启。不過如果你只關(guān)心估計概率最高的類別(即使這個概率并不高),那么可以使用predict_classes()方法:

>>> y_pred = model.predict_classes(X_new)
>>> y_pred
array([9, 2, 1])
>>> np.array(class_names)[y_pred]
array(['Ankle boot', 'Pullover', 'Trouser'], dtype='<U11')

那么模型實際上對這三個圖像都預測正確了(見圖1.13)领舰。

圖1.13 測試集前三張圖像.jpg

好的夫嗓,那么現(xiàn)在我們已經(jīng)學習了如何用Sequential API來搭建、訓練冲秽、評估和使用分類MLP舍咖,那么接下來的文章我們將講述如何搭建回歸MLP以及搭建更加復雜的模型。

敬請期待啦锉桑!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末排霉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子民轴,更是在濱河造成了極大的恐慌攻柠,老刑警劉巖球订,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瑰钮,居然都是意外死亡冒滩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門浪谴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來旦部,“玉大人,你說我怎么就攤上這事较店。” “怎么了容燕?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵梁呈,是天一觀的道長。 經(jīng)常有香客問我蘸秘,道長官卡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任醋虏,我火速辦了婚禮寻咒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘颈嚼。我一直安慰自己毛秘,他們只是感情好,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布阻课。 她就那樣靜靜地躺著叫挟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪限煞。 梳的紋絲不亂的頭發(fā)上抹恳,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天,我揣著相機與錄音署驻,去河邊找鬼奋献。 笑死,一個胖子當著我的面吹牛旺上,可吹牛的內(nèi)容都是我干的瓶蚂。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼抚官,長吁一口氣:“原來是場噩夢啊……” “哼扬跋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起凌节,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤钦听,失蹤者是張志新(化名)和其女友劉穎洒试,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體朴上,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡垒棋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了痪宰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片叼架。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖衣撬,靈堂內(nèi)的尸體忽然破棺而出乖订,到底是詐尸還是另有隱情,我是刑警寧澤具练,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布乍构,位于F島的核電站,受9級特大地震影響扛点,放射性物質(zhì)發(fā)生泄漏哥遮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一陵究、第九天 我趴在偏房一處隱蔽的房頂上張望眠饮。 院中可真熱鬧,春花似錦铜邮、人聲如沸仪召。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽返咱。三九已至,卻和暖如春牍鞠,著一層夾襖步出監(jiān)牢的瞬間咖摹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工难述, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留萤晴,地道東北人。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓胁后,卻偏偏與公主長得像店读,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子攀芯,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容