本章涵蓋了
- 神經(jīng)網(wǎng)絡(luò)的核心組件
- Keras概論
- 設(shè)置深度學(xué)習(xí)工作環(huán)境
- 使用神經(jīng)網(wǎng)絡(luò)來解決基本分類和回歸問題
本章旨在讓你開始使用神經(jīng)網(wǎng)絡(luò)來解決實(shí)際問題。您將鞏固從第2章的第一個(gè)實(shí)際示例中獲得的知識(shí),并將所學(xué)知識(shí)應(yīng)用于三個(gè)新問題孕索,涉及到神經(jīng)網(wǎng)絡(luò)的三個(gè)最常見的用例:二分類、多分類和標(biāo)量回歸肄渗。
在這一章中恳啥,我們將更深入地了解我們?cè)诘诙轮薪榻B的神經(jīng)網(wǎng)絡(luò)的核心組件:層翁垂、網(wǎng)絡(luò)、目標(biāo)函數(shù)和優(yōu)化器。
我們將向您簡(jiǎn)要介紹Keras,這個(gè)Python深度學(xué)習(xí)庫(kù)將貫穿全書。你將建立一個(gè)深度學(xué)習(xí)工作環(huán)境(通過TensorFlow躺同,Keras黄刚,和GPU的支持)侍芝。我們將深入研究如何使用神經(jīng)網(wǎng)絡(luò)解決實(shí)際問題的三個(gè)介紹性示例:
- 分類影評(píng)為積極positive還是消極negative(二分類)
- 按主題分類新聞(多分類)
- 根據(jù)房地產(chǎn)數(shù)據(jù)估算房?jī)r(jià)(回歸)
到本章結(jié)束時(shí)棵红,您將能夠使用神經(jīng)網(wǎng)絡(luò)來解決簡(jiǎn)單的機(jī)器問題,例如向量數(shù)據(jù)的分類和回歸。然后集嵌,您將準(zhǔn)備在第四章中開始構(gòu)建一個(gè)更有原則的、理論驅(qū)動(dòng)的機(jī)器學(xué)習(xí)理解酥泛。
3.1神經(jīng)網(wǎng)絡(luò)剖析
正如你在前幾章看到的异逐,訓(xùn)練神經(jīng)網(wǎng)絡(luò)圍繞以下對(duì)象:
- 層情组,用于合并成網(wǎng)絡(luò)(或模型)
- 輸入數(shù)據(jù)和相應(yīng)的目標(biāo)
- 損失函數(shù),定義了用于學(xué)習(xí)的反饋信號(hào)
- 優(yōu)化器,這決定了學(xué)習(xí)如何進(jìn)行
您可以將它們的交互可視化袍祖,如圖3.1所示:網(wǎng)絡(luò)由連接在一起的層組成,將輸入數(shù)據(jù)映射到預(yù)期值茁肠。然后仅孩,損失函數(shù)將這些預(yù)期值與目標(biāo)進(jìn)行比較京腥,產(chǎn)生一個(gè)損失值:一個(gè)衡量網(wǎng)絡(luò)預(yù)測(cè)與預(yù)期匹配程度的指標(biāo)
。優(yōu)化器使用這個(gè)損失值來更新網(wǎng)絡(luò)的權(quán)重。
讓我們仔細(xì)看看層、網(wǎng)絡(luò)、損失函數(shù)和優(yōu)化器投放。
3.1.1 layers: 深度學(xué)習(xí)的構(gòu)建模塊
神經(jīng)網(wǎng)絡(luò)的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)是layer拜姿,在第二章中已有介紹過。層是一個(gè)數(shù)據(jù)處理模塊批狱,它接受一個(gè)或多個(gè)張量作為輸入琅锻,并輸出一個(gè)或多個(gè)張量僵芹。有些層是無狀態(tài)的凿跳,但更常見的是層有一個(gè)狀態(tài):層的權(quán)值,用隨機(jī)梯度下降法學(xué)習(xí)的一個(gè)或幾個(gè)張量,這些張量一起組成了網(wǎng)絡(luò)的知識(shí)蝴猪。
不同的層適用于不同的張量格式和不同類型的數(shù)據(jù)處理。例如,簡(jiǎn)單的矢量數(shù)據(jù)存儲(chǔ)在二維張量的形狀(samples,features)中,通常由緊密連接的層(densely connected)處理,也稱為完全連接層或密集層(Keras中的密集類)。序列數(shù)據(jù)存儲(chǔ)在形狀為三維張量(samples,timesteps, features),中,通常由循環(huán)層(recurrent)處理,比如LSTM層鹃愤。圖像數(shù)據(jù)存儲(chǔ)在4D張量中吟税,通常由二維卷積層(Conv2D)處理。
你可以把layer看作深度學(xué)習(xí)的樂高積木,這個(gè)比喻是由Keras這樣的框架明確表達(dá)出來的。在Keras中構(gòu)建深度學(xué)習(xí)模型是通過剪切兼容的層來形成有用的數(shù)據(jù)轉(zhuǎn)換管道來完成的。這里的層兼容性指的是每一層只接受特定形狀的輸入張量,并返回特定形狀的輸出張量。
考慮下面的例子:
我們正在創(chuàng)建一個(gè)只接受作為輸入2D張量的層喧兄,其中第一個(gè)維數(shù)是784(軸0,批處理維數(shù)是未指定的,因此任何值都會(huì)被接受)。這一層將返回一個(gè)張量,其中第一維變換為32。
因此,這個(gè)層只能連接到一個(gè)下游層,它需要32維向量作為它的輸入。在使用Keras時(shí),您不必?fù)?dān)心兼容性伊佃,因?yàn)樘砑拥侥P椭械膶邮莿?dòng)態(tài)構(gòu)建的例证,以匹配進(jìn)入層的形狀漠秋。例如,假設(shè)您寫下以下內(nèi)容:
from keras import models
from keras import layers
model = models.Sequential()
model.add(layers.Dense(32, input_shape=(784,)))
model.add(layers.Dense(32))
第二層沒有接收輸入形狀參數(shù)——相反,它會(huì)自動(dòng)推斷出它的輸入形狀是之前層的輸出形狀焰雕。
3.1.2模型:層次網(wǎng)絡(luò)
深度學(xué)習(xí)模型是一個(gè)有向的衷笋、無循環(huán)的層次圖。最常見的實(shí)例是層的線性堆棧矩屁,將單個(gè)輸入映射到單個(gè)輸出。
但是隨著你的深入吝秕,您將接觸到更廣泛的網(wǎng)絡(luò)拓?fù)洳雌辍R恍┏R姷膯栴}包括:
- 二分支網(wǎng)絡(luò)
- 多線程網(wǎng)絡(luò)
- 初始?jí)K(Inception blocks)
網(wǎng)絡(luò)的拓?fù)涠x了一個(gè)假設(shè)空間。你們可能記得第一章中烁峭,我們將機(jī)器學(xué)習(xí)定義為“利用反饋信號(hào)的引導(dǎo)容客,在預(yù)定義的可能性空間內(nèi),搜索一些輸入數(shù)據(jù)的有用表示则剃≡胖”通過選擇網(wǎng)絡(luò)拓?fù)洌憔拖拗屏四愕目赡苄钥臻g(假設(shè)空間)到特定的一系列張量運(yùn)算棍现,將輸入數(shù)據(jù)映射到輸出數(shù)據(jù)调煎。你接下來要找的是這些張量運(yùn)算中涉及到的權(quán)重張量的一組很好的值。
選擇合適的網(wǎng)絡(luò)架構(gòu)與其說是一門科學(xué)己肮,不如說是一門藝術(shù);盡管有一些你可以信賴的最佳實(shí)踐和原則士袄,但只有實(shí)踐才能幫助你成為一個(gè)合適的神經(jīng)網(wǎng)絡(luò)架構(gòu)師。接下來的幾章將教給你構(gòu)建神經(jīng)網(wǎng)絡(luò)的明確原則谎僻,幫助你培養(yǎng)對(duì)特定問題的直覺娄柳。
3.1.3 損失函數(shù)和優(yōu)化器:配置學(xué)習(xí)過程的關(guān)鍵
一旦定義了網(wǎng)絡(luò)架構(gòu),您仍然需要選擇另外兩件事:
- 損失函數(shù)(目標(biāo)函數(shù))-在訓(xùn)練中需要最小化的數(shù)值艘绍。它代表著對(duì)手頭任務(wù)的成功程度的度量赤拒。
- 優(yōu)化器——根據(jù)損失函數(shù)確定網(wǎng)絡(luò)的更新方式。它實(shí)現(xiàn)了隨機(jī)梯度下降(SGD)的一種特殊變體诱鞠。
具有多個(gè)輸出的神經(jīng)網(wǎng)絡(luò)可能具有多個(gè)損失函數(shù)(每個(gè)輸出一個(gè))挎挖。但梯度下降過程必須基于單個(gè)標(biāo)量損失值;因此,對(duì)于多損失網(wǎng)絡(luò)航夺,所有損失(通過平均)合并成一個(gè)標(biāo)量蕉朵。
為正確的問題選擇正確的目標(biāo)函數(shù)是非常重要的:你的網(wǎng)絡(luò)會(huì)走它能走的任何捷徑,以最小化損失;因此阳掐,如果目標(biāo)與手頭任務(wù)的成功程度不完全相關(guān)始衅,你的網(wǎng)絡(luò)最終會(huì)做一些你可能不期望的結(jié)果冷蚂。想象一個(gè)愚蠢的,萬能的人工智能通過SGD進(jìn)行訓(xùn)練汛闸,而目標(biāo)函數(shù)選得很差:“最大化所有活著的人的平均幸福蝙茶。”為了使它的工作更容易蛉拙,這個(gè)人工智能可能會(huì)選擇殺死除少數(shù)人之外的所有人尸闸,并專注于剩下的人的幸福——因?yàn)槠骄腋2皇苁O露嗌偃说挠绊懺谐D强赡懿皇悄阆胍?只要記住,你建立的所有神經(jīng)網(wǎng)絡(luò)在降低損失功能上同樣無情——所以明智地選擇目標(biāo)苞尝,否則你將不得不面對(duì)意想不到的副作用畸肆。
幸運(yùn)的是,當(dāng)涉及到諸如分類宙址、回歸和序列預(yù)測(cè)等常見問題時(shí)轴脐,您可以遵循一些簡(jiǎn)單的指導(dǎo)原則來選擇正確的損失。例如抡砂,對(duì)于一個(gè)兩類分類問題大咱,您將使用二元交叉熵(binary crossentropy),對(duì)于一個(gè)多類分類問題使用分類交叉熵(categorical crossentropy)注益,對(duì)于回歸問題使用均方差(meansquared error)碴巾,對(duì)于序列學(xué)習(xí)問題使用連接主義時(shí)間分類(connectionist temporal classification, CTC)等等。只有當(dāng)你在研究真正新的研究問題時(shí)丑搔,你才需要開發(fā)出自己的目標(biāo)函數(shù)厦瓢。在接下來的幾章中,我們將顯式地詳細(xì)說明在許多常見任務(wù)中應(yīng)該選擇哪些損失函數(shù)啤月。
3.2 Keras簡(jiǎn)介
在本書中煮仇,代碼示例使用Keras (https://keras.io)。Keras是Python的一個(gè)深度學(xué)習(xí)框架谎仲,它提供了一種方便的方式來定義和訓(xùn)練幾乎任何類型的深度學(xué)習(xí)模型浙垫。Keras最初是為研究人員開發(fā)的,目的是實(shí)現(xiàn)快速實(shí)驗(yàn)郑诺。
Keras有以下關(guān)鍵特點(diǎn):
- 它允許相同的代碼在CPU或GPU上無縫運(yùn)行夹姥。
- 它有一個(gè)友好的API,便于快速開發(fā)原型深度學(xué)習(xí)模型。
- 它內(nèi)置支持卷積網(wǎng)絡(luò)(convolutional networks间景,用于計(jì)算機(jī)視覺),復(fù)發(fā)性網(wǎng)絡(luò)(recurrent networks佃声,用于序列處理),以及兩者的結(jié)合。
- 它支持任意網(wǎng)絡(luò)體系結(jié)構(gòu):多輸入和多輸出模型,共享層,共享模型等等倘要。這意味著Keras適用于構(gòu)建任何深度學(xué)習(xí)模型十拣,從生成式對(duì)抗性網(wǎng)絡(luò)(generative adversarial network)到神經(jīng)圖靈機(jī)(neural Turing machine)。
Keras是以MIT license發(fā)布的志鹃,這意味著它可以在商業(yè)項(xiàng)目中自由使用夭问。它兼容任何版本的Python,從 2.7到3.6(2017年中期)曹铃。
Keras擁有超過20萬的用戶缰趋,從初創(chuàng)公司和大公司的學(xué)術(shù)研究人員和工程師到研究生和業(yè)余愛好者。Keras在谷歌陕见、Netflix秘血、Uber、CERN评甜、Yelp灰粮、Square以及數(shù)百家致力于解決各種問題的初創(chuàng)公司中都有應(yīng)用。Keras也是機(jī)器學(xué)習(xí)競(jìng)賽網(wǎng)站Kaggle上一個(gè)很受歡迎的框架
3.2.1 Keras, TensorFlow, Theano, and CNTK
Keras是一個(gè)模型級(jí)庫(kù)忍坷,提供了開發(fā)深度學(xué)習(xí)模型的高級(jí)構(gòu)建模塊粘舟。它不處理低級(jí)操作,如張量操作和微分佩研。相反弊攘,它依賴于一個(gè)專門的带欢、經(jīng)過良好優(yōu)化的張量庫(kù),充當(dāng)Keras的后端引擎。不是選擇單個(gè)張量庫(kù)并將Keras的實(shí)現(xiàn)與該庫(kù)綁定在一起迹鹅,而是以模塊化的方式處理問題
(參見圖3.3);因此咳短,可以將幾個(gè)不同的后端引擎無縫地插入到Keras中倒源。目前攘蔽,現(xiàn)有的三個(gè)后端實(shí)現(xiàn)是TensorFlow后端、Theano后端和Microsoft Cognitive工具包(CNTK)的后端政模。在未來岗宣,Keras可能會(huì)被擴(kuò)展到使用更deep-learning的執(zhí)行引擎。
TensorFlow淋样、CNTK和Theano是當(dāng)今深度學(xué)習(xí)的一些主要平臺(tái)耗式。Theano (http://deeplearning.net/software/theano)由蒙特利爾大學(xué)的MILA實(shí)驗(yàn)室開發(fā),TensorFlow (www.tensorflow.org)由谷歌開發(fā)趁猴,CNTK(https://github.com/Microsoft/CNTK)由微軟開發(fā)刊咳。您使用Keras編寫的任何代碼片段都可以與這些后端一起運(yùn)行,而無需更改代碼中的任何內(nèi)容:在開發(fā)過程中儡司,您可以無縫地在兩者之間切換娱挨,這通常被證明是有用的——例如,如果這些后端中有一個(gè)對(duì)于特定任務(wù)來說速度更快的話捕犬。
我們建議將TensorFlow后端作為大多數(shù)深度學(xué)習(xí)需求的默認(rèn)設(shè)置跷坝,因?yàn)樗亲顝V泛采用的酵镜、可擴(kuò)展的和有生產(chǎn)力的。
通過TensorFlow(或Theano柴钻,或CNTK)淮韭, Keras可以在cpu和gpu兩者上無縫運(yùn)行。在CPU上運(yùn)行時(shí)贴届,TensorFlow本身為張量操作包裝了一個(gè)低級(jí)庫(kù)靠粪,稱為Eigen(http://feat.tuxfamily.org)。在GPU, TensorFlow封裝了一個(gè)優(yōu)化深度學(xué)習(xí)操作庫(kù),稱之為NVIDIA CUDA深度神經(jīng)網(wǎng)絡(luò)庫(kù)(cuDNN)毫蚓。
3.2.2用Keras開發(fā):快速概述
您已經(jīng)看到了Keras模型的一個(gè)示例:MNIST示例占键。典型的Keras工作流看起來就像那個(gè)例子:
- 定義你的訓(xùn)練數(shù)據(jù):輸入張量和目標(biāo)張量。
- 定義一個(gè)層(或模型)網(wǎng)絡(luò)绍些,用于將您的輸入映射到您的目標(biāo)捞慌。
- 通過選擇損失函數(shù)、優(yōu)化器和一些要監(jiān)控的指標(biāo)來配置學(xué)習(xí)過程柬批。
- 通過調(diào)用模型的fit()方法迭代您的訓(xùn)練數(shù)據(jù)。
定義模型有兩種方法:使用Sequential
類(僅用于線性層堆棧袖订,這是目前最常見的網(wǎng)絡(luò)體系結(jié)構(gòu))或functional
API(用于層的有向無環(huán)圖氮帐,它允許您構(gòu)建完全任意的體系結(jié)構(gòu))。
作為復(fù)習(xí)洛姑,這里有一個(gè)使用Sequential
類定義的兩層模型(注意上沐,我們將輸入數(shù)據(jù)的預(yù)期形狀傳遞給第一層):
from keras import models
from keras import layers
model = models.Sequential()
model.add(layers.Dense(32, activation='relu', input_shape=(784,)))
model.add(layers.Dense(10, activation='softmax'))
下面是使用functional
API定義的相同模型:
input_tensor = layers.Input(shape=(784,))
x = layers.Dense(32, activation='relu')(input_tensor)
output_tensor = layers.Dense(10, activation='softmax')(x)
model = models.Model(inputs=input_tensor, outputs=output_tensor)
通過functional
API,你可以操縱模型處理的數(shù)據(jù)張量楞艾,并將層應(yīng)用到這個(gè)張量上参咙,就好像它們是函數(shù)一樣。
請(qǐng)注意硫眯,有關(guān)如何使用
functional
API的詳細(xì)指南可以在第7章中找到蕴侧。在第7章之前,我們只在代碼示例中使用Sequential
類两入。
一旦定義了模型體系結(jié)構(gòu)净宵,是否使用了Sequential
模型或functional` API。以下所有步驟都是相同的裹纳。
學(xué)習(xí)過程是在編譯步驟中配置的择葡,在這個(gè)步驟中,您指定了模型應(yīng)該使用的優(yōu)化器和損失函數(shù)剃氧,以及您希望在訓(xùn)練期間監(jiān)控的指標(biāo)敏储。這里有一個(gè)單損失函數(shù)的例子,這是目前最常見的情況:
from keras import optimizers
model.compile(optimizer=optimizers.RMSprop(lr=0.001),
loss='mse',
metrics=['accuracy'])
最后朋鞍,學(xué)習(xí)過程由通過fit()方法向模型傳遞輸入數(shù)據(jù)(以及相應(yīng)的目標(biāo)數(shù)據(jù))的Numpy數(shù)組組成已添,類似于在Scikit-Learn和其他幾個(gè)機(jī)器學(xué)習(xí)庫(kù)中所做的工作:
model.fit(input_tensor, target_tensor, batch_size=128, epochs=10)
在接下來的幾章中妥箕,您將對(duì)哪種類型的網(wǎng)絡(luò)架構(gòu)適用于不同類型的問題,如何選擇正確的學(xué)習(xí)配置酝碳,以及如何調(diào)整模型矾踱,直到它給出您想要的結(jié)果,建立一個(gè)堅(jiān)實(shí)的直覺疏哗。我們將在3.4呛讲、3.5和3.6節(jié)中查看三個(gè)基本示例:一個(gè)二分類示例、一個(gè)多分類示例和一個(gè)回歸示例返奉。
3.3 設(shè)置深度學(xué)習(xí)工作環(huán)境
在您開始開發(fā)深度學(xué)習(xí)應(yīng)用程序之前贝搁,您需要設(shè)置您的工作環(huán)境。強(qiáng)烈建議您在一個(gè)現(xiàn)代的NVIDIA GPU上運(yùn)行深度學(xué)習(xí)代碼芽偏,盡管這不是必須的雷逆。有些應(yīng)用程序——特別是卷積網(wǎng)絡(luò)的圖像處理和循環(huán)神經(jīng)網(wǎng)絡(luò)(recurrent neural)的序列處理——在CPU上的速度會(huì)非常慢,甚至是一個(gè)快速的多核CPU污尉。甚至對(duì)于實(shí)際可以在CPU上運(yùn)行的應(yīng)用程序膀哲,您通常會(huì)看到使用現(xiàn)代GPU的速度提高了5到10倍。如果您不想在您的機(jī)器上安裝GPU被碗,您可以考慮在AWS EC2 GPU實(shí)例或谷歌云平臺(tái)上運(yùn)行您的實(shí)驗(yàn)某宪。但是請(qǐng)注意隨著時(shí)間的推移,云GPU實(shí)例可能變得昂貴锐朴。
無論您是在本地運(yùn)行還是在云中運(yùn)行兴喂,最好使用Unix工作環(huán)境。雖然在Windows上使用Keras在技術(shù)上是可能的(所有三個(gè)Keras后端都支持Windows)焚志,但我們不推薦它衣迷。在附錄A的安裝說明中,我們將考慮Ubuntu機(jī)器酱酬。如果你是Windows用戶壶谒,讓一切正常運(yùn)行的最簡(jiǎn)單的解決方案就是在你的機(jī)器上設(shè)置一個(gè)Ubuntu雙啟動(dòng)。這似乎是一個(gè)麻煩岳悟,但從長(zhǎng)遠(yuǎn)來看佃迄,使用Ubuntu會(huì)節(jié)省很多時(shí)間和麻煩。
注意贵少,為了使用Keras呵俏,您需要安裝TensorFlow或CNTK或Theano (如果你想在這三個(gè)后端之間來回切換,也可以選擇全部)滔灶。在這本書中普碎,我們將重點(diǎn)介紹TensorFlow,并給出一些與Theano相關(guān)的簡(jiǎn)單說明录平。我們不覆蓋CNTK的說明麻车。
3.3.1 Jupyter記事本:進(jìn)行深度學(xué)習(xí)實(shí)驗(yàn)的首選方式
Jupyter notebook是進(jìn)行深度學(xué)習(xí)實(shí)驗(yàn)的好方法——尤其是本書中的許多代碼示例缀皱。它們廣泛應(yīng)用于數(shù)據(jù)科學(xué)和機(jī)器學(xué)習(xí)領(lǐng)域。notebook是一個(gè)由Jupyter notebook應(yīng)用程序(https://jupyter.org)生成的文件动猬,您可以在瀏覽器中編輯它啤斗。它將Python代碼的執(zhí)行能力與豐富的文本編輯功能結(jié)合在一起,以注釋您正在做的事情赁咙。notebook還允許你將長(zhǎng)時(shí)間的實(shí)驗(yàn)分解成更小的部分钮莲,這些部分可以獨(dú)立執(zhí)行,這使得開發(fā)具有交互性彼水,并且意味著如果在實(shí)驗(yàn)后期出現(xiàn)問題崔拥,你不必重新運(yùn)行之前的所有代碼。
我們建議使用Jupyter notebook開始使用Keras凤覆,盡管這不是一個(gè)要求:您還可以運(yùn)行獨(dú)立的Python腳本或從PyCharm等IDE中運(yùn)行代碼链瓦。本書中的所有代碼示例都可以作為開源 notebooks使用;你可以從這本書的網(wǎng)站www.manning.com/books/deep-learning-with-python獲取。
3.3.2 讓Keras跑起來:兩個(gè)選項(xiàng)
為了開始實(shí)踐盯桦,我們建議以下兩種選項(xiàng)之一:
- 使用官方的EC2深度學(xué)習(xí)AMI (https://aws.amazon.com/amazonai/amis)慈俯,在EC2上以Jupyter notebook方式運(yùn)行Keras實(shí)驗(yàn)。如果您的本地機(jī)器上還沒有GPU拥峦,請(qǐng)這樣做肥卡。附錄B提供了一步一步的指南。
- 在本地Unix工作站上從頭開始安裝所有內(nèi)容事镣。然后,您可以運(yùn)行本地Jupyter notebook或常規(guī)Python代碼庫(kù)揪胃。如果你已經(jīng)有一個(gè)高端的英偉達(dá)GPU璃哟,那就這么做。附錄A提供了一個(gè)特定于ubuntu的分步指南喊递。
讓我們更仔細(xì)地看一看選擇一個(gè)選項(xiàng)而不是另一個(gè)選項(xiàng)所涉及的一些妥協(xié)随闪。
3.3.3在云計(jì)算中運(yùn)行深度學(xué)習(xí)工作:利弊
如果你還沒有一個(gè)可以用于深度學(xué)習(xí)的GPU(一個(gè)最近發(fā)布的高端NVIDIA GPU),以在云端進(jìn)行深度學(xué)習(xí)實(shí)驗(yàn)骚勘,這是一種簡(jiǎn)單铐伴、低成本的方式,讓您無需購(gòu)買任何額外的硬件即可開始工作俏讹。如果您正在使用Jupyter notebook当宴,那么在云端運(yùn)行的體驗(yàn)與在本地運(yùn)行沒什么不同。從2017年年中開始泽疆,讓深度學(xué)習(xí)變得最容易的云服務(wù)無疑是AWS EC2户矢。附錄B提供了在EC2 GPU實(shí)例上運(yùn)行Jupyter notebooks的逐步指南。
但如果你是深度學(xué)習(xí)的忠實(shí)用戶殉疼,這種設(shè)置在很長(zhǎng)一段時(shí)間內(nèi)都是不可持續(xù)的梯浪,甚至在幾個(gè)星期內(nèi)也是不可持續(xù)的捌年。EC2實(shí)例非常昂貴:附錄B中推薦的實(shí)例類型(p2.xlarge instance在2017年年中的價(jià)格為每小時(shí)0.90美元,它不會(huì)為你提供太多電力挂洛。同時(shí)礼预,一個(gè)堅(jiān)實(shí)的消費(fèi)階層,GPU的價(jià)格在1000美元到1500美元之間——隨著時(shí)間的推移虏劲,這個(gè)價(jià)格是相當(dāng)穩(wěn)定的托酸,即使這些GPU的規(guī)格不斷改進(jìn)。如果您對(duì)深度學(xué)習(xí)很認(rèn)真伙单,您應(yīng)該使用一個(gè)或多個(gè)gpu建立一個(gè)本地工作站获高。
簡(jiǎn)而言之,EC2是一個(gè)很好的入門方法吻育。您可以完全在EC2 GPU實(shí)例上遵循本書中的代碼示例念秧。但如果你想成為深度學(xué)習(xí)的超級(jí)用戶,那就擁有自己的gpu布疼。
3.3.4 深度學(xué)習(xí)最好的GPU是什么?
如果你要買GPU摊趾,你應(yīng)該選擇哪一個(gè)?首先要注意的是它一定是NVIDIA GPU。英偉達(dá)是迄今為止唯一一家在深度學(xué)習(xí)方面投入巨資的圖形計(jì)算公司游两,而現(xiàn)代深度學(xué)習(xí)框架只能在英偉達(dá)卡上運(yùn)行砾层。
2017年年中,我們推薦NVIDIA TITAN Xp作為市場(chǎng)上最好的深度學(xué)習(xí)卡贱案。對(duì)于較低的預(yù)算肛炮,您可能需要考慮使用GTX 1060。如果你是在2018年或更晚的時(shí)候閱讀這些頁(yè)面宝踪,花點(diǎn)時(shí)間在網(wǎng)上尋找更新鮮的推薦侨糟,因?yàn)槊磕甓紩?huì)有新的款式出現(xiàn)。
從本節(jié)開始瘩燥,我們將假設(shè)您可以訪問具有以下功能的機(jī)器(安裝好Keras和它的依賴)——最好有GPU支持秕重。確保在繼續(xù)之前完成這個(gè)步驟。仔細(xì)閱讀附錄中的逐步指南厉膀,如果需要進(jìn)一步的幫助溶耘,可以上網(wǎng)查找。關(guān)于如何安裝Keras和常見的深度學(xué)習(xí)依賴關(guān)系的教程很多服鹅。
我們現(xiàn)在可以深入研究Keras的實(shí)際例子凳兵。
3.4 電影評(píng)論分類:一個(gè)二元分類的例子
二分類或二元分類可能是應(yīng)用最廣泛的機(jī)器學(xué)習(xí)問題。在本例中菱魔,您將學(xué)習(xí)如何根據(jù)評(píng)論的文本內(nèi)容將電影評(píng)論分為正面評(píng)論和負(fù)面評(píng)論留荔。
3.4.1 IMDB數(shù)據(jù)集
您將使用IMDB數(shù)據(jù)集:一套50,000份高度兩極化評(píng)論的互聯(lián)網(wǎng)電影數(shù)據(jù)庫(kù)。它們分為25000條訓(xùn)練評(píng)論和25000條測(cè)試評(píng)論,每一組由50%的負(fù)面評(píng)論和50%的正面評(píng)論組成聚蝶。
為什么要使用單獨(dú)的訓(xùn)練和測(cè)試集?因?yàn)槟阌肋h(yuǎn)不應(yīng)該用你用來訓(xùn)練它的數(shù)據(jù)來測(cè)試一個(gè)機(jī)器學(xué)習(xí)模型!僅僅因?yàn)槟P驮谄溆?xùn)練數(shù)據(jù)上表現(xiàn)良好并不意味著它將在它從未見過的數(shù)據(jù)上表現(xiàn)良好;您所關(guān)心的是您的模型在新數(shù)據(jù)上的性能(因?yàn)槟呀?jīng)知道了您的訓(xùn)練數(shù)據(jù)的標(biāo)簽——顯然您不需要您的模型來預(yù)測(cè)這些數(shù)據(jù))杰妓。
例如 ,您的模型最終可能只是記住了訓(xùn)練樣本與其目標(biāo)之間的映射碘勉,這對(duì)于預(yù)測(cè)模型從未見過的數(shù)據(jù)的目標(biāo)來說是無用的巷挥。我們將在下一章更詳細(xì)地討論這一點(diǎn)。
與MNIST數(shù)據(jù)集一樣验靡,IMDB數(shù)據(jù)集也附帶在Keras中倍宾。它已經(jīng)經(jīng)過預(yù)處理:評(píng)論(單詞序列)已經(jīng)被轉(zhuǎn)換成整數(shù)序列,其中每個(gè)整數(shù)代表字典中的一個(gè)特定單詞胜嗓。
下面的代碼將加載數(shù)據(jù)集(當(dāng)您第一次運(yùn)行它時(shí)高职,大約80 MB的數(shù)據(jù)將下載到您的計(jì)算機(jī))。
Listing 3.1 Loading the IMDB dataset
from keras.datasets import imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)
參數(shù)num_words=10000意味著您將只保留訓(xùn)練數(shù)據(jù)中最常見的10,000個(gè)單詞辞州。罕見的單詞將被丟棄怔锌。這允許您處理可管理大小的向量數(shù)據(jù)。
train_data和test_data變量是review(評(píng)論)的列表;每個(gè)評(píng)論都是一個(gè)單詞索引列表(編碼一個(gè)單詞序列)变过。train_label和test_label是0和1的列表埃元,0代表否定,1代表肯定:
>>> train_data[0]
[1, 14, 22, 16, ... 178, 32]
>>> train_labels[0]
1
因?yàn)槟惆炎约合拗圃谧畛S玫?萬個(gè)單詞媚狰,所以沒有一個(gè)單詞的索引超過1萬個(gè):
>>> max([max(sequence) for sequence in train_data])
9999
下面是如何快速將這些評(píng)論翻譯回英語的方法單詞:
3.4.2 準(zhǔn)備數(shù)據(jù)
你不能把整數(shù)列表輸入神經(jīng)網(wǎng)絡(luò)岛杀。你必須把列表變成張量。有兩種方法:
-
填補(bǔ)你的列表,這樣他們都有相同的長(zhǎng)度
,把它們變成一個(gè)整數(shù)形狀張量(samples,word_indices),然后在網(wǎng)絡(luò)的第一層使用一個(gè)能夠處理這種整數(shù)張量的層(嵌入(Embedding)層崭孤,我們將在本書后面詳細(xì)介紹)类嗤。 -
將列表編碼為0和1的向量(One-hot encode)
。這將意味著辨宠,例如土浸,將序列[3,5]轉(zhuǎn)換成10000維的向量,除了指標(biāo)3和5彭羹,所有的0都是0,也就是1泪酱。然后派殷,可以使用密集(Dense)層作為網(wǎng)絡(luò)的第一層,能夠處理浮點(diǎn)向量數(shù)據(jù)墓阀。
讓我們使用后一種解決方案對(duì)數(shù)據(jù)進(jìn)行矢量化毡惜,您將手動(dòng)對(duì)數(shù)據(jù)進(jìn)行矢量化,以獲得最大的清晰度斯撮。
Listing 3.2 Encoding the integer sequences into a binary matrix
現(xiàn)在樣例變成這樣子:
>>> x_train[0]
array([ 0., 1., 1., ..., 0., 0., 0.])
你也應(yīng)該對(duì)你的標(biāo)簽進(jìn)行矢量化经伙,這很簡(jiǎn)單:
y_train = np.asarray(train_labels).astype('float32')
y_test = np.asarray(test_labels).astype('float32')
現(xiàn)在數(shù)據(jù)已經(jīng)準(zhǔn)備好輸入神經(jīng)網(wǎng)絡(luò)。
3.4.3 構(gòu)建你的network
輸入數(shù)據(jù)是向量,標(biāo)簽是標(biāo)量(1和0):這是您遇到的最簡(jiǎn)單的設(shè)置帕膜。在這種問題上表現(xiàn)良好的一種網(wǎng)絡(luò)是一個(gè)簡(jiǎn)單的堆棧枣氧,由完全連接(密集Dense)層與relu激活函數(shù)構(gòu)成:Dense(16,activation='relu')。傳遞給每個(gè)Dense層的參數(shù)(16)是該層的隱藏單元(hidden unit)數(shù)垮刹。隱藏單元是層表示空間中的維度达吞。
你可能還記得在第2章中,每個(gè)這樣的密集層都有一個(gè)relu激活實(shí)現(xiàn)了以下張量操作鏈:
output = relu(dot(W, input) + b)
有16個(gè)隱藏單元意味著權(quán)重矩陣W將有形狀(input_dimension荒典,16):與W的點(diǎn)積將把輸入數(shù)據(jù)投影到一個(gè)16維的表示空間上(然后加上偏差向量b酪劫,再應(yīng)用relu運(yùn)算)。您可以直觀地理解表示空間的維數(shù)寺董,即“在學(xué)習(xí)內(nèi)部表示時(shí)覆糟,您允許網(wǎng)絡(luò)擁有多大的自由度”。擁有更多的隱藏單元(高維表示空間)可以讓網(wǎng)絡(luò)學(xué)習(xí)更復(fù)雜的表示遮咖,但這會(huì)使網(wǎng)絡(luò)的計(jì)算成本更高滩字,并可能導(dǎo)致學(xué)習(xí)不需要的模式(模式將提高訓(xùn)練數(shù)據(jù)的性能,但不會(huì)提高測(cè)試數(shù)據(jù)的性能)
對(duì)于這樣一堆密集層盯滚,有兩個(gè)關(guān)鍵的架構(gòu)決策需要做出:
- 使用多少個(gè)layers
- 針對(duì)每個(gè)layer踢械,選取多少個(gè)hidden unit
在第四章,你將學(xué)習(xí)正式的原則來指導(dǎo)你做出這些選擇魄藕。就目前而言内列,您必須相信我的架構(gòu)選擇:
- 兩個(gè)中間層,每個(gè)層有16個(gè)隱藏單元
- 第三層將輸出關(guān)于當(dāng)前評(píng)論情緒的標(biāo)量預(yù)測(cè)
中間層使用relu作為激活函數(shù)背率,最后一層使用sigmoid激活话瞧,輸出一個(gè)概率(0到1之間的值,指示樣本有多大可能具有目標(biāo)“1”:評(píng)論有多大可能是正面的)寝姿。relu(整流線性單元)是一個(gè)函數(shù)交排,它的作用是消除負(fù)值(參見圖3.4),而sigmoid將任意值“壓縮”到[0,1]區(qū)間(參見圖3.5)饵筑,輸出一些可以解釋為概率的東西埃篓。
線性整流函數(shù)
Sigmoid函數(shù)
圖3.6顯示了網(wǎng)絡(luò)的外觀。這是Keras的實(shí)現(xiàn)根资,類似于之前看到的MNIST的例子架专。
Listing 3.3 The model definition
from keras import models
from keras import layers
model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
- 什么是激活函數(shù),為什么它們是必要的?
如果沒有像relu(也稱為非線性)這樣的激活函數(shù)玄帕,Dense層將由兩個(gè)線性操作組成——點(diǎn)積和一個(gè)加法:
output = dot(W, input) + b
因此部脚,該層只能學(xué)習(xí)輸入數(shù)據(jù)的線性變換(仿射變換,affine transformations)):該層的假設(shè)空間是輸入數(shù)據(jù)到16維空間的所有可能的線性變換的集合。這樣的假設(shè)空間過于有限裤纹,不會(huì)從多層表示中獲益委刘,因?yàn)橐淮蠖丫€性層仍然會(huì)實(shí)現(xiàn)線性操作:添加更多的層不會(huì)擴(kuò)展假設(shè)空間。
為了獲得一個(gè)更豐富的假設(shè)空間,從深度表示中獲益锡移,你需要一個(gè)非線性呕童,或者激活函數(shù)。relu是深度學(xué)習(xí)中最受歡迎的激活函數(shù)罩抗,但是還有很多其他的候選函數(shù)拉庵,它們都有同樣奇怪的名字:prelu, elu等等。
最后套蒂,您需要選擇損失函數(shù)和優(yōu)化器钞支。因?yàn)槟忝媾R一個(gè)二元分類問題網(wǎng)絡(luò)的輸出是一個(gè)概率(你用一個(gè)s型激活單元層結(jié)束你的網(wǎng)絡(luò)),最好選用binary_crossentropy loss函數(shù)操刀。這不是唯一可行的選擇:例如烁挟,您可以使用mean_squared_error。但是當(dāng)你處理輸出概率的模型時(shí)骨坑,交叉熵(Crossentropy)通常是最好的選擇撼嗓。交叉熵是信息領(lǐng)域中的一個(gè)量測(cè)量概率分布之間的距離的理論,在這種情況下欢唾,測(cè)量真實(shí)分布和預(yù)測(cè)之間的距離的理論且警。
下面是使用rmsprop優(yōu)化器和binary_crossentropy loss函數(shù)配置模型的步驟。請(qǐng)注意礁遣,您還將在訓(xùn)練期間監(jiān)控accuracy:
Listing 3.4 Compiling the model
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])
您正在將優(yōu)化器斑芜、損失函數(shù)和度量作為字符串傳遞,這是可能的祟霍,因?yàn)閞msprop杏头、binary_crossentropy和accuracy都打包為Keras的一部分。有時(shí)沸呐,您可能希望配置優(yōu)化器的參數(shù)醇王,或者傳遞一個(gè)自定義損失函數(shù)或度量函數(shù)。前者可以通過將優(yōu)化器類實(shí)例作為optimizer參數(shù)傳遞來實(shí)現(xiàn)崭添,如清單3.5所示;后者可以通過將函數(shù)對(duì)象作為loss和/或metrics參數(shù)傳遞來完成寓娩,如清單3.6所示。
Listing 3.5 Configuring the optimizer
from keras import optimizers
model.compile(optimizer=optimizers.RMSprop(lr=0.001),
loss='binary_crossentropy',
metrics=['accuracy'])
Listing 3.6 Using custom losses and metrics
from keras import losses
from keras import metrics
model.compile(optimizer=optimizers.RMSprop(lr=0.001),
loss=losses.binary_crossentropy,
metrics=[metrics.binary_accuracy])
3.4.4 驗(yàn)證你的方法
為了在訓(xùn)練期間監(jiān)控模型對(duì)以前從未見過的數(shù)據(jù)的準(zhǔn)確性呼渣,您將通過從原始訓(xùn)練數(shù)據(jù)中分離10,000個(gè)樣本來創(chuàng)建一個(gè)驗(yàn)證集衡招。
Listing 3.7 Setting aside a validation set
x_val = x_train[:10000]
partial_x_train = x_train[10000:]
y_val = y_train[:10000]
partial_y_train = y_train[10000:]
現(xiàn)在呀打,您將對(duì)模型以小批量512個(gè)樣本毛仪,進(jìn)行20次epoch (x_train和y_train張量中的所有樣本進(jìn)行20次迭代)契讲。與此同時(shí)畸裳,你將監(jiān)測(cè)你分開的10,000個(gè)樣品的損失和準(zhǔn)確性缰犁。您可以將驗(yàn)證數(shù)據(jù)作為validation_data參數(shù)傳遞。
Listing 3.8 Training your mode
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['acc'])
history = model.fit(partial_x_train,
partial_y_train,
epochs=20,
batch_size=512,
validation_data=(x_val, y_val))
在CPU上,每次迭代將花費(fèi)不到2秒的時(shí)間——訓(xùn)練在20秒內(nèi)結(jié)束帅容。在每一個(gè)迭代結(jié)束時(shí)颇象,當(dāng)模型計(jì)算它對(duì)10,000個(gè)驗(yàn)證數(shù)據(jù)樣本的損失和準(zhǔn)確性時(shí),會(huì)有一個(gè)輕微的暫停并徘。
注意遣钳,對(duì)model.fit()的調(diào)用返回一個(gè)History對(duì)象。這個(gè)對(duì)象有一個(gè)成員history麦乞,這是一個(gè)字典蕴茴,包含了所有在訓(xùn)練期間發(fā)生的數(shù)據(jù)。讓我們來看看:
>>> history_dict = history.history
>>> history_dict.keys()
[u'acc', u'loss', u'val_acc', u'val_loss']
該詞典包含4個(gè)條目:在訓(xùn)練和驗(yàn)證期間監(jiān)視的每個(gè)度量值有一個(gè)條目姐直。在下面的兩個(gè)list中倦淀,我們使用Matplotlib并排繪制訓(xùn)練和驗(yàn)證損失(參見圖3.7),以及訓(xùn)練和驗(yàn)證準(zhǔn)確性(參見圖3.8)声畏。注意撞叽,由于網(wǎng)絡(luò)的隨機(jī)初始化不同,您自己的結(jié)果可能略有不同插龄。
Listing 3.9 Plotting the training and validation loss
import matplotlib.pyplot as plt
history_dict = history.history
loss_values = history_dict['loss']
val_loss_values = history_dict['val_loss']
epochs = range(1, len(acc) + 1)
plt.plot(epochs, loss_values, 'bo', label='Training loss')
plt.plot(epochs, val_loss_values, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
Listing 3.10 Plotting the training and validation accuracy
plt.clf()
acc_values = history_dict['acc']
val_acc_values = history_dict['val_acc']
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
如你所見愿棋,訓(xùn)練損失隨時(shí)間的變化而減小,訓(xùn)練精度(accuracy)隨時(shí)間的變化而增加均牢。這就是您在運(yùn)行梯度下降優(yōu)化時(shí)所期望的——您試圖最小化的數(shù)量應(yīng)該隨著每次迭代而減少糠雨。但驗(yàn)證損失和準(zhǔn)確性卻并非如此:它們似乎在第四次迭代達(dá)到頂峰。這是我們之前警告過的一個(gè)例子:
在訓(xùn)練數(shù)據(jù)上表現(xiàn)更好的模型不一定會(huì)在以前從未見過的數(shù)據(jù)上表現(xiàn)更好膨处。確切地說见秤,您看到的是過度擬合:在第二個(gè)階段之后,您正在對(duì)訓(xùn)練數(shù)據(jù)進(jìn)行過度優(yōu)化真椿,最終您將學(xué)習(xí)到特定于訓(xùn)練數(shù)據(jù)的表示鹃答,而不是泛化到訓(xùn)練集之外的數(shù)據(jù)。
在這種情況下突硝,為了防止過度訓(xùn)練测摔,你可以在3次迭代后停止訓(xùn)練。通常解恰,您可以使用一系列技術(shù)來減輕過度擬合锋八,我們將在第4章中介紹。
讓我們從零開始訓(xùn)練一個(gè)新的網(wǎng)絡(luò)护盈,為期四個(gè)迭代挟纱,然后在測(cè)試數(shù)據(jù)上評(píng)估它。
Listing 3.11 Retraining a model from scratch
model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=4, batch_size=512)
results = model.evaluate(x_test, y_test)
最終的結(jié)果如下:
>>> results
[0.2929924130630493, 0.88327999999999995]
這種相當(dāng)簡(jiǎn)單的方法的準(zhǔn)確率達(dá)到88%腐宋。使用最頂尖的方法紊服,您應(yīng)該能夠接近95%檀轨。
3.4.5 使用訓(xùn)練過的網(wǎng)絡(luò)對(duì)新數(shù)據(jù)進(jìn)行預(yù)測(cè)
在訓(xùn)練了網(wǎng)絡(luò)之后,您將希望在實(shí)際環(huán)境中使用它欺嗤。你可以使用預(yù)測(cè)方法產(chǎn)生正面評(píng)論的可能性:
>>> model.predict(x_test)
array([[ 0.98006207]
[ 0.99758697]
[ 0.99975556]
...,
[ 0.82167041]
[ 0.02885115]
[ 0.65371346]], dtype=float32)
如您所見参萄,對(duì)于某些樣本(0.99或以上,或0.01或更少)煎饼,網(wǎng)絡(luò)是自信的讹挎,而對(duì)于其他樣本(0.6或0.4),網(wǎng)絡(luò)是不自信的吆玖。
3.4.6進(jìn)一步實(shí)驗(yàn)
以下實(shí)驗(yàn)將幫助說服你筒溃,你的架構(gòu)選擇都相當(dāng)合理,但仍有改進(jìn)的余地:
- 你使用兩個(gè)隱藏層。嘗試使用一個(gè)或三個(gè)隱藏層衰伯,看看這樣做如何影響驗(yàn)證和測(cè)試準(zhǔn)確性铡羡。
- 嘗試使用層有更多隱藏的單位或更少的隱藏單位:32單元,64單元等等。
- 嘗試使用mse代替binary_crossentropy損失函數(shù)意鲸。
- 嘗試使用tanh激活函數(shù)(一種在神經(jīng)網(wǎng)絡(luò)早期很流行的激活函數(shù))而不是relu烦周。
3.4.7結(jié)束
以下是你應(yīng)該從這個(gè)例子中吸取的教訓(xùn):
- 您通常需要對(duì)原始數(shù)據(jù)進(jìn)行相當(dāng)多的預(yù)處理,以便能夠?qū)⑵渥鳛閺埩枯斎氲缴窠?jīng)網(wǎng)絡(luò)中怎顾。單詞序列可以編碼為二進(jìn)制向量读慎,但也有其他編碼選項(xiàng)。
- 使用relu激活函數(shù)的Dense層可以解決廣泛的問題(包括情緒分類)槐雾,你可能會(huì)經(jīng)常使用它們夭委。
- 在二分類問題(兩個(gè)輸出類)中,網(wǎng)絡(luò)應(yīng)該以一個(gè)(隱藏)單元和一個(gè)sigmoid激活函數(shù)的密集(Dense)層結(jié)束:網(wǎng)絡(luò)的輸出應(yīng)該是0到1之間的標(biāo)量募强,編碼一個(gè)概率株灸。
- 在二元分類問題上有這樣一個(gè)標(biāo)量sigmoid輸出的場(chǎng)景,您應(yīng)該使用的損失函數(shù)是binary_crossentropy擎值。
- 無論您有什么問題慌烧,
rmsprop優(yōu)化器
通常都是一個(gè)足夠好的選擇。這是你不用擔(dān)心的一件事鸠儿。 - 隨著他們?cè)谟?xùn)練數(shù)據(jù)上的進(jìn)步屹蚊,神經(jīng)網(wǎng)絡(luò)最終開始過擬合,最終在他們從未見過的數(shù)據(jù)上得到越來越糟糕的結(jié)果进每。一定要始終監(jiān)視訓(xùn)練集之外的數(shù)據(jù)的性能汹粤。
3.5 分類新聞專線:一個(gè)多分類的例子
在上一節(jié)中,您看到了如何使用緊密連接(densely connected)的神經(jīng)網(wǎng)絡(luò)將向量輸入分類為兩個(gè)相互排斥的類田晚。但是如果你有兩種以上的分類會(huì)發(fā)生什么呢?
在本節(jié)中嘱兼,您將構(gòu)建一個(gè)網(wǎng)絡(luò),將路透社新聞專線分為46個(gè)相互排斥的主題贤徒。因?yàn)槟阌泻芏囝惽酆荆@個(gè)問題是一個(gè)多分類的實(shí)例;而且胃惜,由于每個(gè)數(shù)據(jù)點(diǎn)都應(yīng)該被劃分為一個(gè)類別,因此問題更具體地說就是一個(gè)單標(biāo)簽哪雕、多分類(single-label, multiclass classification.)的實(shí)例。如果每個(gè)數(shù)據(jù)點(diǎn)可能屬于多個(gè)類別(在本例中是主題)鲫趁,那么您將面臨一個(gè)多標(biāo)簽斯嚎、多分類(multilabel, multiclass classification)問題。
3.5.1路透社數(shù)據(jù)集
您將使用路透社數(shù)據(jù)集(Reuters dataset)挨厚,這是一組簡(jiǎn)短的新聞專線及其主題堡僻,由路透社(Reuters)于1986年發(fā)布。這是一個(gè)簡(jiǎn)單的疫剃,廣泛使用的用于文本分類的玩具數(shù)據(jù)集钉疫。有46個(gè)不同的主題;有些主題比其他主題更有代表性,但是每個(gè)主題在訓(xùn)練集中至少有10個(gè)例子巢价。
像IMDB和MNIST一樣牲阁,路透數(shù)據(jù)集也是Keras的一部分。讓我們來看看壤躲。
Listing 3.12 Loading the Reuters dataset
from keras.datasets import reuters
(train_data, train_labels), (test_data, test_labels) = reuters.load_data(
num_words=10000)
與IMDB數(shù)據(jù)集一樣城菊,參數(shù)num_words=10000將數(shù)據(jù)限制為在數(shù)據(jù)中發(fā)現(xiàn)的10000個(gè)最常見的單詞。
您有8,982個(gè)培訓(xùn)示例和2,246個(gè)測(cè)試示例:
>>> len(train_data)
8982
>>> len(test_data)
2246
與IMDB評(píng)論一樣碉克,每個(gè)示例都是一個(gè)整數(shù)列表(單詞索引):
>>> train_data[10]
[1, 245, 273, 207, 156, 53, 74, 160, 26, 14, 46, 296, 26, 39, 74, 2979,
3554, 14, 46, 4689, 4329, 86, 61, 3499, 4795, 14, 61, 451, 4329, 17, 12]
下面是你如何把它解碼成文字的方法凌唬,以滿足你的好奇心。
Listing 3.13 Decoding newswires back to text
與示例關(guān)聯(lián)的標(biāo)簽是0到45之間的整數(shù)——主題索引
>>> train_labels[10]
3
3.5.2 準(zhǔn)備數(shù)據(jù)
您可以使用與前面示例完全相同的代碼對(duì)數(shù)據(jù)進(jìn)行矢量化
Listing 3.14 Encoding the data
要對(duì)標(biāo)簽進(jìn)行矢量化漏麦,有兩種可能:您可以將標(biāo)簽列表轉(zhuǎn)換為整數(shù)張量客税,或者您可以使用one-hot編碼。one-hot編碼是一種廣泛用于分類數(shù)據(jù)的格式撕贞,也稱為分類編碼(categorical encoding)更耻。有關(guān)one-hot編碼的更詳細(xì)解釋,請(qǐng)參閱第6.1節(jié)麻掸。在本例中酥夭,標(biāo)簽的one-hot編碼包括將每個(gè)標(biāo)簽嵌入為一個(gè)全零向量,在標(biāo)簽索引的位置用1代替脊奋。這里有一個(gè)例子:
注意熬北,在Keras中有一種內(nèi)置的方法可以做到這一點(diǎn),您已經(jīng)在MNIST示例中看到了這一點(diǎn):
from keras.utils.np_utils import to_categorical
one_hot_train_labels = to_categorical(train_labels)
one_hot_test_labels = to_categorical(test_labels)
3.5.3 構(gòu)建網(wǎng)絡(luò)
這個(gè)主題分類問題與前面的電影評(píng)論分類問題類似:在這兩種情況下诚隙,您都試圖對(duì)簡(jiǎn)短的文本片段進(jìn)行分類讶隐。但是這里有一個(gè)新的限制:輸出類的數(shù)量從2個(gè)增加到46個(gè)。輸出空間的維數(shù)要大得多久又。
在您使用過的Dense層堆棧中巫延,每個(gè)層只能訪問前一層輸出的信息效五。如果有一層掉了一些與分類問題相關(guān)的信息,這些信息后續(xù)的層永遠(yuǎn)無法恢復(fù):每一層都可能成為信息瓶頸炉峰。在前面的示例中畏妖,您使用了16維的中間層,但是一個(gè)16維的空間可能太有限疼阔,無法學(xué)習(xí)如何分離46個(gè)不同的類:這樣的小層可能成為信息瓶頸戒劫,永久地刪除相關(guān)信息。
因此婆廊,您將使用更大的層迅细,共64個(gè)單元。
Listing 3.15 Model definition
from keras import models
from keras import layers
model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(46, activation='softmax'))
關(guān)于這個(gè)架構(gòu)淘邻,還有兩件事需要注意:
- 以大小為46的Dense層結(jié)束網(wǎng)絡(luò)茵典。這意味著對(duì)于每個(gè)輸入樣本,網(wǎng)絡(luò)將輸出一個(gè)46維的向量宾舅。這個(gè)向量中的每個(gè)元素
(每個(gè)維度)將編碼不同的輸出類统阿。 - 最后一層使用softmax激活。您在MNIST示例中看到了這種模式贴浙。這意味著網(wǎng)絡(luò)將輸出46個(gè)不同輸出類的概率分布——對(duì)于每個(gè)輸入樣本砂吞,網(wǎng)絡(luò)將產(chǎn)生一個(gè)46維的輸出向量,其中output[i]是樣本屬于i類的概率崎溃。
在這種情況下蜻直,最好的損失函數(shù)是categorical_crossentropy。它測(cè)量了兩個(gè)概率分布之間的距離:這里袁串,網(wǎng)絡(luò)輸出的概率分布和標(biāo)簽的真實(shí)分布之間的距離概而。通過最小化這兩個(gè)分布之間的距離,您可以訓(xùn)練網(wǎng)絡(luò)輸出盡可能接近真實(shí)標(biāo)簽的內(nèi)容囱修。
Listing 3.16 Compiling the mode
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
3.5.4 驗(yàn)證你的方法
讓我們?cè)谟?xùn)練數(shù)據(jù)中分別設(shè)置1000個(gè)樣本作為驗(yàn)證集赎瑰。
x_val = x_train[:1000]
partial_x_train = x_train[1000:]
y_val = one_hot_train_labels[:1000]
partial_y_train = one_hot_train_labels[1000:]s
現(xiàn)在,讓我們對(duì)網(wǎng)絡(luò)進(jìn)行20次的訓(xùn)練
Listing 3.18 Training the model
history = model.fit(partial_x_train, partial_y_train,epochs=20,batch_size=512,validation_data=(x_val, y_val))
最后破镰,讓我們顯示它的損失和精度曲線(見圖3.9和3.10)餐曼。
Listing 3.19 Plotting the training and validation loss
import matplotlib.pyplot as plt
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(loss) + 1)
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
Listing 3.20 Plotting the training and validation accuracy
plt.clf()
acc = history.history['acc']
val_acc = history.history['val_acc']
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
網(wǎng)絡(luò)在經(jīng)歷了九個(gè)迭代之后開始過擬合。讓我們從零開始訓(xùn)練一個(gè)新的網(wǎng)絡(luò)鲜漩,歷時(shí)9個(gè)迭代源譬,然后在測(cè)試集中評(píng)估它。
Listing 3.21 Retraining a model from scratch
model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(46, activation='softmax'))
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(partial_x_train, partial_y_train, epochs=9, batch_size=512, validation_data=(x_val, y_val))
results = model.evaluate(x_test, one_hot_test_labels)
以下是最終結(jié)果:
>>> results
[0.9565213431445807, 0.79697239536954589]
這種方法的準(zhǔn)確率達(dá)到約80%孕似。對(duì)于平衡二分類問題踩娘,純隨機(jī)分類器的準(zhǔn)確率為50%。但在這種情況下喉祭,它接近19%养渴, 所以結(jié)果看起來相當(dāng)不錯(cuò)雷绢,至少與隨機(jī)基線相比是這樣的:
>>> import copy
>>> test_labels_copy = copy.copy(test_labels)
>>> np.random.shuffle(test_labels_copy)
>>> hits_array = np.array(test_labels) == np.array(test_labels_copy)
>>> float(np.sum(hits_array)) / len(test_labels)
0.18655387355298308
3.5.5 對(duì)新數(shù)據(jù)進(jìn)行預(yù)測(cè)
您可以驗(yàn)證模型實(shí)例的predict方法返回所有46個(gè)主題的概率分布。讓我們?yōu)樗袦y(cè)試數(shù)據(jù)生成主題預(yù)測(cè)理卑。
Listing 3.22 Generating predictions for new data
predictions = model.predict(x_test)
預(yù)測(cè)中的每一項(xiàng)都是長(zhǎng)度為46的向量:
>>> predictions[0].shape
(46,)
這個(gè)向量系數(shù)的和是1:
>>> np.sum(predictions[0])
1.0
最大的條目是預(yù)測(cè)類——概率最高的類:
>>> np.argmax(predictions[0])
4
3.5.6 另一種處理標(biāo)簽和損失的方法
我們之前提到過翘紊,編碼標(biāo)簽的另一種方法是將它們轉(zhuǎn)換成整數(shù)張量,如下所示:
y_train = np.array(train_labels)
y_test = np.array(test_labels)
這種方法唯一會(huì)改變的是損失函數(shù)的選擇藐唠。清單3.21中使用的loss函數(shù)categorical_crossentropy期望label遵循分類編碼霞溪。對(duì)于整數(shù)標(biāo)簽,您應(yīng)該使用sparse_categorical_crossentropy:
model.compile(optimizer='rmsprop',
loss='sparse_categorical_crossentropy',
metrics=['acc'])
這個(gè)新的損失函數(shù)在數(shù)學(xué)上仍然與categorical_crossentropy相同;它只是有一個(gè)不同的接口中捆。
3.5.7具有足夠大的中間層的重要性
我們?cè)谇懊嫣岬竭^,因?yàn)樽罱K的輸出是46維的坊饶,所以應(yīng)該避免中間層的隱藏單元遠(yuǎn)遠(yuǎn)少于46個(gè)⌒刮保現(xiàn)在讓我們看看當(dāng)你引入一個(gè)信息瓶頸時(shí),如果中間層明顯小于46維:例如匿级,4維:
Listing 3.23 A model with an information bottleneck
model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(4, activation='relu'))
model.add(layers.Dense(46, activation='softmax'))
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(partial_x_train, partial_y_train, epochs=20, batch_size=128, validation_data=(x_val, y_val))
現(xiàn)在網(wǎng)絡(luò)的validation accuracy達(dá)到了71%蟋滴,下降了8%。這種下降主要是由于您試圖將大量信息(需要足夠的信息以恢復(fù)46個(gè)類的分離超平面)壓縮到過低維的中間空間痘绎。網(wǎng)絡(luò)能夠?qū)⒋蟛糠直匾男畔⑷M(jìn)這些八維表示中津函,但并不是全部。
3.5.8進(jìn)一步的實(shí)驗(yàn)
- 嘗試使用更大或更小的層:32個(gè)單元孤页,128個(gè)單元等等尔苦。
- 你使用兩個(gè)隱藏層。現(xiàn)在嘗試使用一個(gè)隱藏層行施,或者三個(gè)隱藏層允坚。
3.5.9 結(jié)尾
以下是你應(yīng)該從這個(gè)例子中吸取的教訓(xùn):
- 如果您試圖在N個(gè)類中分類數(shù)據(jù)點(diǎn),那么您的網(wǎng)絡(luò)應(yīng)該以大小為N的Dense層結(jié)尾蛾号。
- 在單標(biāo)簽稠项、多類分類問題中,網(wǎng)絡(luò)應(yīng)該以softmax激活函數(shù)結(jié)束鲜结,這樣它就會(huì)輸出一個(gè)在N輸出類上的概率分布展运。
- Categorical crossentropy幾乎總是這種問題的損失函數(shù)。它使網(wǎng)絡(luò)輸出的概率分布與目標(biāo)的真實(shí)分布之間的距離最小化精刷。
- 在多類分類中有兩種處理標(biāo)簽的方法:
--通過分類編碼(也稱為one-hot編碼)拗胜,并使用categorical_crossentropy作為損失函數(shù)對(duì)標(biāo)簽進(jìn)行編碼
-- 將標(biāo)簽編碼為整數(shù),并使用sparse_categorical_crossentropy loss函數(shù)
- 如果需要將數(shù)據(jù)分類為大量的類別贬养,則應(yīng)該避免由于中間層太小而在網(wǎng)絡(luò)中造成信息瓶頸
3.6預(yù)測(cè)房?jī)r(jià):一個(gè)回歸例子
前面的兩個(gè)例子被認(rèn)為是分類問題挤土,目標(biāo)是預(yù)測(cè)輸入數(shù)據(jù)點(diǎn)的單個(gè)離散標(biāo)簽。另一種常見的機(jī)器學(xué)習(xí)問題是回歸误算,它由預(yù)測(cè)連續(xù)值而不是離散標(biāo)簽組成
:例如仰美,給定的氣象數(shù)據(jù),預(yù)測(cè)明天的溫度;或者給定它的規(guī)格,預(yù)測(cè)一個(gè)軟件項(xiàng)目完成的時(shí)間.
注意: 不要混淆回歸和logistic regression算法迷殿。令人困惑的是,logistic regression不是一種回歸算法——而是一種分類算法咖杂。
3.6.1波士頓房?jī)r(jià)數(shù)據(jù)集
你將嘗試?yán)媒o出的當(dāng)時(shí)該郊區(qū)的數(shù)據(jù)點(diǎn)庆寺,比如犯罪率,當(dāng)?shù)胤慨a(chǎn)稅率等等诉字,預(yù)測(cè)20世紀(jì)70年代中期波士頓某郊區(qū)的房?jī)r(jià)中值懦尝。您將使用的數(shù)據(jù)集與前面兩個(gè)示例有一個(gè)有趣的區(qū)別。它的數(shù)據(jù)點(diǎn)相對(duì)較少:只有506個(gè)壤圃,分為404個(gè)訓(xùn)練樣本和102個(gè)測(cè)試樣本陵霉。以及輸入數(shù)據(jù)中的每個(gè)特征(例如,犯罪率)有不同的規(guī)模伍绳。例如踊挠,有些值是概率,它們的值在0和1之間;另一些取1到1之間的值等等冲杀。
Listing 3.24 Loading the Boston housing dataset
from keras.datasets import boston_housing
(train_data, train_targets), (test_data, test_targets) = boston_housing.load_data()
查看下數(shù)據(jù):
>>> train_data.shape
(404, 13)
>>> test_data.shape
(102, 13)
如您所見效床,您有404個(gè)訓(xùn)練樣本和102個(gè)測(cè)試樣本,每個(gè)樣本都有13個(gè)數(shù)值特征权谁,例如人均犯罪率剩檀、人均住房數(shù)量、高速公路的可達(dá)性等等旺芽。
目標(biāo)是業(yè)主自住房屋的中值沪猴,單位為數(shù)千美元:
>>> train_targets
[ 15.2, 42.3, 50. ... 19.4, 19.4, 29.1]
價(jià)格一般在1萬到5萬美元之間。如果這聽起來很便宜采章,請(qǐng)記住字币,這是在上世紀(jì)70年代中期,而且這些價(jià)格沒有根據(jù)通脹進(jìn)行調(diào)整共缕。
3.6.2準(zhǔn)備數(shù)據(jù)
如果將所有的神經(jīng)網(wǎng)絡(luò)值都包含在大不相同的范圍內(nèi)洗出,那將是一個(gè)問題。網(wǎng)絡(luò)可能能夠自動(dòng)適應(yīng)這種異構(gòu)數(shù)據(jù)图谷,但它肯定會(huì)使學(xué)習(xí)變得更加困難翩活。廣泛的最佳實(shí)踐來處理這樣的數(shù)據(jù)是feature的normalization:對(duì)于輸入數(shù)據(jù)中的每個(gè)特征(輸入數(shù)據(jù)矩陣中的一列),減去特征的平均值并除以標(biāo)準(zhǔn)差便贵,使特征的中心為0菠镇,并且有一個(gè)單位標(biāo)準(zhǔn)差。這在Numpy中很容易做到承璃。
Listing 3.25 Normalizing the data
mean = train_data.mean(axis=0)
train_data -= mean
std = train_data.std(axis=0)
train_data /= std
test_data -= mean
test_data /= std
注意利耍,用于標(biāo)準(zhǔn)化測(cè)試數(shù)據(jù)的數(shù)值是使用訓(xùn)練數(shù)據(jù)計(jì)算的。
您永遠(yuǎn)不應(yīng)該在您的工作流中使用對(duì)測(cè)試數(shù)據(jù)進(jìn)行任何數(shù)量的計(jì)算,即使對(duì)于像數(shù)據(jù)規(guī)范化這樣簡(jiǎn)單的事情也是如此隘梨。
備注:0均值標(biāo)準(zhǔn)化(Z-score standardization)
0均值歸一化方法將原始數(shù)據(jù)集歸一化為均值為0程癌、方差1的數(shù)據(jù)集,歸一化公式如下:
其中轴猎,μ嵌莉、σ分別為原始數(shù)據(jù)集的均值和標(biāo)準(zhǔn)。該種歸一化方式要求原始數(shù)據(jù)的分布可以近似為高斯分布捻脖,否則歸一化的效果會(huì)變得很糟糕锐峭。
在分類、聚類算法中可婶,需要使用距離來度量相似性的時(shí)候沿癞、或者使用PCA技術(shù)進(jìn)行降維的時(shí)候,第二種方法(Z-score standardization)表現(xiàn)更好矛渴。
3.6.3 構(gòu)建網(wǎng)絡(luò)
由于可供使用的樣本非常少抛寝,所以您將使用一個(gè)非常小的網(wǎng)絡(luò),其中包含兩個(gè)隱藏層曙旭,每個(gè)層有64個(gè)單元。一般來說晶府,您擁有的訓(xùn)練數(shù)據(jù)越少桂躏,過度擬合就越糟糕,使用一個(gè)小網(wǎng)絡(luò)是緩解過度擬合的一種方法川陆。
Listing 3.26 Model definition
網(wǎng)絡(luò)以1個(gè)單元結(jié)束,沒有激活函數(shù)(它將是一個(gè)線性層)剂习。這是標(biāo)量回歸的一個(gè)典型設(shè)置(在你試圖預(yù)測(cè)單個(gè)連續(xù)值的情況下)。
應(yīng)用激活函數(shù)將限制輸出的范圍,例如,如果將sigmoid激活函數(shù)應(yīng)用到最后一層,則網(wǎng)絡(luò)只能學(xué)會(huì)預(yù)測(cè)0到1之間的值较沪。在這里鳞绕,因?yàn)樽詈笠粚邮羌兙€性的,網(wǎng)絡(luò)可以自由地學(xué)習(xí)在任何范圍內(nèi)預(yù)測(cè)值尸曼。注意们何,您使用mse損失函數(shù)---均方差(即預(yù)測(cè)和目標(biāo)差的平方)來編譯網(wǎng)絡(luò)。這是一個(gè)廣泛用于回歸問題的損失函數(shù)控轿。
您還在訓(xùn)練期間監(jiān)視一個(gè)新的度量:平均絕對(duì)誤差(MAE冤竹,備注:MAD=(x-mean(x))./n;)。它是預(yù)測(cè)和目標(biāo)之間差值的絕對(duì)值茬射。例如鹦蠕,在這個(gè)問題上的平均誤差為0.5美元意味著你的預(yù)測(cè)平均誤差為500美元。
3.6.4使用K-fold驗(yàn)證來驗(yàn)證您的方法(備注:交叉驗(yàn)證法)
為了評(píng)估您的網(wǎng)絡(luò)在抛,同時(shí)不斷調(diào)整它的參數(shù)(例如用于訓(xùn)練的epochs的數(shù)量)钟病,您可以將數(shù)據(jù)分為訓(xùn)練集和驗(yàn)證集,就像前面的示例所做的那樣。但是由于數(shù)據(jù)點(diǎn)太少肠阱,驗(yàn)證集最終會(huì)非常小(例如票唆,大約100個(gè)示例)。因此辖所,驗(yàn)證分值可能會(huì)根據(jù)您選擇使用哪些數(shù)據(jù)點(diǎn)進(jìn)行驗(yàn)證惰说,以及您選擇了哪些數(shù)據(jù)點(diǎn)進(jìn)行訓(xùn)練而發(fā)生很大的變化:根據(jù)驗(yàn)證分割,驗(yàn)證分值可能有很大的差異缘回。這將妨礙您可靠地評(píng)估您的模型吆视。
這種情況下的最佳實(shí)踐是使用K-fold交叉驗(yàn)證(參見圖3.11)。它包括將可用數(shù)據(jù)分成K個(gè)分區(qū)(通常K = 4或5)酥宴,實(shí)例化K個(gè)相同的模型啦吧,并在K - 1分區(qū)上對(duì)每個(gè)模型進(jìn)行訓(xùn)練,同時(shí)對(duì)其余分區(qū)進(jìn)行評(píng)估拙寡。使用的模型的驗(yàn)證分?jǐn)?shù)是得到的K個(gè)驗(yàn)證分?jǐn)?shù)的平均值授滓。就代碼而言,這很簡(jiǎn)單肆糕。
Listing 3.27 K-fold validation
在num_epochs = 100中運(yùn)行這個(gè)程序會(huì)得到以下結(jié)果:
>>> all_scores
[2.588258957792037, 3.1289568449719116, 3.1856116051248984, 3.0763342615401386]
>>> np.mean(all_scores)
2.9947904173572462
不同的運(yùn)行確實(shí)顯示了相當(dāng)不同的驗(yàn)證分?jǐn)?shù)般堆,從2.6到3.2。平均值(3.0)比任何一個(gè)分?jǐn)?shù)都要可靠得多——這就是K-fold交叉驗(yàn)證的全部要點(diǎn)诚啃。在這種情況下淮摔,你平均損失了3000美元,考慮到價(jià)格從1萬美元到5萬美元始赎,這是很重要的和橙。
讓我們?cè)囍丫W(wǎng)絡(luò)訓(xùn)練得更長(zhǎng)一點(diǎn):500次迭代。為了記錄模型在每個(gè)epoch中的表現(xiàn)造垛,您將修改訓(xùn)練循環(huán)以保存每次epoch驗(yàn)證得分日志魔招。
Listing 3.28 Saving the validation logs at each fold
然后,您可以計(jì)算所有折疊項(xiàng)的每個(gè)epoch MAE得分的平均值五辽。
Listing 3.29 Building the history of successive mean K-fold validation scores
average_mae_history = [np.mean([x[i] for x in all_mae_histories]) for i in range(num_epochs)]
讓我們繪制它;見圖3.12
Listing 3.30 Plotting validation scores
import matplotlib.pyplot as plt
plt.plot(range(1, len(average_mae_history) + 1), average_mae_history)
plt.xlabel('Epochs')
plt.ylabel('Validation MAE')
plt.show()
由于規(guī)模問題和相對(duì)較高的方差办斑,可能很難看到圖。讓我們做以下事情:
- 省略前10個(gè)數(shù)據(jù)點(diǎn)杆逗,這些數(shù)據(jù)點(diǎn)與曲線的其他部分的尺度不同俄周。
- 將每個(gè)點(diǎn)替換為前面點(diǎn)的指數(shù)移動(dòng)平均值,以獲得平滑曲線髓迎。
結(jié)果如圖3.13所示
Listing 3.31 Plotting validation scores, excluding the first 10 data points
def smooth_curve(points, factor=0.9):
smoothed_points = []
for point in points:
if smoothed_points:
previous = smoothed_points[-1]
smoothed_points.append(previous * factor + point * (1 - factor))
else:
smoothed_points.append(point)
return smoothed_points
smooth_mae_history = smooth_curve(average_mae_history[10:])
plt.plot(range(1, len(smooth_mae_history) + 1), smooth_mae_history)
plt.xlabel('Epochs')
plt.ylabel('Validation MAE')
plt.show()
根據(jù)這個(gè)圖峦朗,驗(yàn)證MAE在80年代后停止明顯的改善。過了這個(gè)點(diǎn)排龄,你就開始過擬合了波势。
一旦你完成了優(yōu)化模型的其他參數(shù)(除了epochs的數(shù)量外,您還可以調(diào)整隱藏層的大小),你可以用最好的參數(shù)翎朱,訓(xùn)練最終生產(chǎn)模型的訓(xùn)練數(shù)據(jù),然后看看它的性能測(cè)試數(shù)據(jù)。
Listing 3.32 Training the final model
最終的結(jié)果是:
>>> test_mae_score
2.5532484335057877
你還差2550美元尺铣。
3.6.5 結(jié)尾
以下是你應(yīng)該從這個(gè)例子中吸取的教訓(xùn):
- 回歸是使用不同于我們用于分類的損失函數(shù)來完成的拴曲。均方誤差(Mean squared error, MSE)是一種常用的回歸損失函數(shù)。
- 同樣凛忿,用于回歸的評(píng)價(jià)指標(biāo)與用于分類的評(píng)價(jià)指標(biāo)不同;當(dāng)然澈灼,accuracy的概念并不適用于回歸。一個(gè)常見的回歸指標(biāo)是平均絕對(duì)誤差(MAE)店溢。
- 當(dāng)輸入數(shù)據(jù)中的特征具有不同范圍的值時(shí)叁熔,每個(gè)特征都應(yīng)該作為預(yù)處理步驟獨(dú)立地進(jìn)行縮放。
- 當(dāng)可用數(shù)據(jù)很少時(shí)床牧,使用K-fold驗(yàn)證是可靠地評(píng)估模型的好方法荣回。
- 當(dāng)可用的訓(xùn)練數(shù)據(jù)很少時(shí),最好使用一個(gè)隱藏層很少的小網(wǎng)絡(luò)(通常只有一個(gè)或兩個(gè))戈咳,以避免嚴(yán)重的過擬合心软。
章節(jié)總結(jié)
- 現(xiàn)在您可以處理向量數(shù)據(jù)上最常見的機(jī)器學(xué)習(xí)任務(wù):二分類、多分類和標(biāo)量回歸著蛙。本章前面的“總結(jié)”部分總結(jié)了關(guān)于這類任務(wù)的要點(diǎn)删铃。
- 在將原始數(shù)據(jù)輸入神經(jīng)網(wǎng)絡(luò)之前,通常需要對(duì)其進(jìn)行預(yù)處理踏堡。
- 當(dāng)您的數(shù)據(jù)具有不同范圍的特性時(shí)稀颁,作為預(yù)處理的一部分间狂,獨(dú)立地縮放每個(gè)特性猛铅。
- 隨著訓(xùn)練的進(jìn)行寇窑,神經(jīng)網(wǎng)絡(luò)最終開始過適應(yīng)缎患,并在從未見過的數(shù)據(jù)上得到更糟糕的結(jié)果慕的。
- 如果你沒有太多的訓(xùn)練數(shù)據(jù),使用一個(gè)只有一兩個(gè)隱藏層的小網(wǎng)絡(luò)挤渔,以避免嚴(yán)重的過度擬合肮街。
- 如果您的數(shù)據(jù)被劃分為許多類別,如果您使中間層太小判导,可能會(huì)導(dǎo)致信息瓶頸嫉父。
- 對(duì)比分類,回歸使用不同的損失函數(shù)和不同的評(píng)價(jià)指標(biāo)眼刃。
- 當(dāng)您處理少量數(shù)據(jù)時(shí)绕辖,K-fold驗(yàn)證可以幫助可靠地評(píng)估您的模型。
備注:關(guān)于指數(shù)平均數(shù)指標(biāo):https://baike.baidu.com/item/EMA擂红,要比較均價(jià)的趨勢(shì)快慢時(shí)仪际,用EMA更穩(wěn)定;有時(shí),在均價(jià)值不重要時(shí)树碱,也用EMA來平滑和美觀曲線肯适。