深度學(xué)習(xí) 3 步驟
深度學(xué)習(xí)以及 NLP 領(lǐng)域的學(xué)問(wèn)博大精深拜隧,但一般來(lái)說(shuō)召噩,當(dāng)你想要實(shí)際動(dòng)手寫(xiě)出一個(gè)神經(jīng)網(wǎng)路的時(shí)候鼠渺,有 3 個(gè)基本步驟可以 follow:
用深度學(xué)習(xí)框架 Keras 來(lái)實(shí)作深度學(xué)習(xí)的基本 3 步驟 (圖片來(lái)源)
- 定義神經(jīng)網(wǎng)路的架構(gòu)
- 決定如何衡量模型的表現(xiàn)
- 訓(xùn)練模型并挑選最好的結(jié)果
接下來(lái)你會(huì)看到肩杈,大約 80 % 的程式碼會(huì)花在實(shí)作第一個(gè)步驟嗤放。剩馀 2 個(gè)步驟在使用 Keras 的情況下非常容易就能實(shí)現(xiàn)没隘;但后面我們也會(huì)談到,你將花 80 % 的時(shí)間在最后一個(gè)步驟上面。
首先求豫,先讓我們進(jìn)入第一步驟。
定義神經(jīng)網(wǎng)路的架構(gòu)
在實(shí)作之前诉稍,先讓我們回顧一下前面段落看到的模型架構(gòu):
本文用來(lái)實(shí)現(xiàn)假新聞分類的神經(jīng)網(wǎng)路架構(gòu)
從左到右掃過(guò)一遍蝠嘉,你可以很清楚地發(fā)現(xiàn)我們需要以下 5 個(gè)元素來(lái)完成這個(gè)模型:
- 兩個(gè)新聞標(biāo)題(兩個(gè)長(zhǎng)度為 20 的數(shù)字序列)
- 一個(gè)詞嵌入層:將數(shù)字序列轉(zhuǎn)換為詞向量序列
- 一個(gè) LSTM 層:讀入前層的詞向量并萃取標(biāo)題語(yǔ)義
- 一個(gè)串接層:將兩個(gè)新聞標(biāo)題的處理結(jié)果(也是向量)串接成一個(gè)向量
- 一個(gè)全連接層:將前層的向量轉(zhuǎn)換為 3 個(gè)分類的預(yù)測(cè)機(jī)率
有些層我們已經(jīng)在前面章節(jié)看過(guò) Keras 的實(shí)現(xiàn),比方說(shuō)詞嵌入層以及 LSTM 層杯巨。剩下的串接層以及全連結(jié)層在 Keras 也都有現(xiàn)成的模組可供使用蚤告。
另外值得一提的是,圖上的每個(gè)層(Layer)以及向量右下的灰字都對(duì)應(yīng)了底下 Python 程式碼裡頭的變數(shù)名稱:
灰字代表程式碼裡頭對(duì)應(yīng)的變數(shù)名稱
因此服爷,如果等等你不了解底下某個(gè)特定的變數(shù)所代表的意義杜恰,可以回來(lái)利用這張架構(gòu)圖來(lái)釐清概念。
以下就是此模型的 Keras 實(shí)作:
-
基本參數(shù)設(shè)置仍源,有幾個(gè)分類
NUM_CLASSES = 3 # 在語(yǔ)料庫(kù)裡有多少詞彙 MAX_NUM_WORDS = 10000 # 一個(gè)標(biāo)題最長(zhǎng)有幾個(gè)詞彙 MAX_SEQUENCE_LENGTH = 20 # 一個(gè)詞向量的維度 NUM_EMBEDDING_DIM = 256 # LSTM 輸出的向量維度 NUM_LSTM_UNITS = 128
- 建立孿生 LSTM 架構(gòu)(Siamese LSTM) from keras import Input from keras.layers import Embedding, \ LSTM, concatenate, Dense from keras.models import Model ##### 分別定義 2 個(gè)新聞標(biāo)題 A & B 為模型輸入 ##### 兩個(gè)標(biāo)題都是一個(gè)長(zhǎng)度為 20 的數(shù)字序列 top_input = Input( shape=(MAX_SEQUENCE_LENGTH, ), dtype='int32') bm_input = Input( shape=(MAX_SEQUENCE_LENGTH, ), dtype='int32') ##### 詞嵌入層 ##### 經(jīng)過(guò)詞嵌入層的轉(zhuǎn)換心褐,兩個(gè)新聞標(biāo)題都變成 ##### 一個(gè)詞向量的序列,而每個(gè)詞向量的維度 ##### 為 256 embedding_layer = Embedding( MAX_NUM_WORDS, NUM_EMBEDDING_DIM) top_embedded = embedding_layer( top_input) bm_embedded = embedding_layer( bm_input) ##### LSTM 層 ##### 兩個(gè)新聞標(biāo)題經(jīng)過(guò)此層后 ##### 為一個(gè) 128 維度向量 shared_lstm = LSTM(NUM_LSTM_UNITS) top_output = shared_lstm(top_embedded) bm_output = shared_lstm(bm_embedded) ##### 串接層將兩個(gè)新聞標(biāo)題的結(jié)果串接單一向量 ##### 方便跟全連結(jié)層相連 merged = concatenate( [top_output, bm_output], axis=-1) ##### 全連接層搭配 Softmax Activation ##### 可以回傳 3 個(gè)成對(duì)標(biāo)題 ##### 屬于各類別的可能機(jī)率 dense = Dense( units=NUM_CLASSES, activation='softmax') predictions = dense(merged) ##### 我們的模型就是將數(shù)字序列的輸入笼踩,轉(zhuǎn)換 ##### 成 3 個(gè)分類的機(jī)率的所有步驟 / 層的總和 model = Model( inputs=[top_input, bm_input], outputs=predictions)
這段程式碼的確不短檬寂,但有將近一半是我寫(xiě)給你的注解。而且這段程式碼的邏輯跟上面的架構(gòu)圖一模一樣戳表,只差架構(gòu)圖是從左到右桶至、程式碼是從上到下而已。
為了確保用 Keras 定義出的模型架構(gòu)跟預(yù)期相同匾旭,我們也可以將其畫(huà)出來(lái):
from keras.utils import plot_model plot_model( model, to_file='model.png', show_shapes=True, show_layer_names=False, rankdir='LR')
除了模型架構(gòu)以外镣屹,我們還可以看到所有層的輸入 / 輸出張量(Tensor)的維度。在 Keras 里頭价涝,張量的第 1 個(gè)維度通常為樣本數(shù)(比方說(shuō) 5 則新聞標(biāo)題)女蜈,而 None
則代表可以指定任意值。
最重要的是,這個(gè)用 Keras 定義出來(lái)的模型伪窖,跟我們之前想像中的孿生神經(jīng)網(wǎng)路可以說(shuō)是一模一樣:
我沒(méi)有騙你逸寓,對(duì)吧?
現(xiàn)在你應(yīng)該發(fā)現(xiàn)覆山,只要擁有前面幾章學(xué)到的 NLP 知識(shí)以及基礎(chǔ) Python 程式能力竹伸,要建立一個(gè)像這樣看似複雜的孿生 LSTM(Siamese LSTM)神經(jīng)網(wǎng)路其實(shí)也并沒(méi)有那麼困難。
事實(shí)上簇宽,使用 Keras 建立深度學(xué)習(xí)模型這件事情感覺(jué)上就像是在玩疊疊樂(lè)一樣勋篓,一層加上一層:
一位研究生利用 Keras 做深度學(xué)習(xí)的心得 (圖片來(lái)源)
全連接層
唯一沒(méi)有在前面章節(jié)提到的是全連接層(Fully Connected Layer)以及其使用的 Softmax 函式。
全連接層顧名思義魏割,代表該層的每個(gè)神經(jīng)元(Neuron)都會(huì)跟前一層的所有神經(jīng)元享有連結(jié):
因?yàn)橹恍枰A(yù)測(cè) 3 個(gè)分類譬嚣,本文的全連接層只有 3 個(gè)神經(jīng)元
而為了確認(rèn)我們計(jì)算的參數(shù)量無(wú)誤,還可以使用 model.summary()
來(lái)看每一層的參數(shù)量以及輸出的張量(Tensor)長(zhǎng)相:
model.summary()
全連接層在最下面钞它。而因?yàn)槠渑c前一層「緊密」連接的緣故拜银,它在 Keras 里頭被稱為 Dense
層。它也是最早出現(xiàn)遭垛、最簡(jiǎn)單的神經(jīng)網(wǎng)路層之一盐股。
Param #
則紀(jì)錄了每一層所包含的模型參數(shù)(Parameters)。在機(jī)器學(xué)習(xí)的過(guò)程中耻卡,這些參數(shù)都會(huì)不斷地被調(diào)整疯汁,直到能讓模型能做出很好的預(yù)測(cè)。詞嵌入層有最多的參數(shù)卵酪,因?yàn)槲覀円獮?字典裡頭的每個(gè)詞彙都建立一個(gè) 256 維度的詞向量幌蚊,因此參數(shù)量為 10,000 * 256。
這張表另外一個(gè)值得注意的地方是所有層的 Output Shape 的第一個(gè)維度都是 None
溃卡。而 None
代表著可以是任意的數(shù)字溢豆。
在 Keras 裡頭,第一個(gè)維度代表著樣本數(shù)(#Samples)瘸羡,比方說(shuō)前 9,527 筆新聞標(biāo)題 A 的數(shù)字序列的 shape
應(yīng)該要是 (9527, 20)
:
x1_train[:9527].shape
嗯漩仙,結(jié)果跟我們想像的一樣。
而之所以每層的樣本數(shù)為 None
是因?yàn)?Keras 為了因應(yīng)在不同場(chǎng)合會(huì)丟入不同數(shù)量的樣本需求犹赖。比方說(shuō)队他,在訓(xùn)練時(shí)你可能會(huì)一次丟 32 筆資料給模型訓(xùn)練,但在預(yù)測(cè)的時(shí)候一次只丟 16 筆資料峻村。
Softmax 函式
Softmax 函式一般都會(huì)被用在整個(gè)神經(jīng)網(wǎng)路的最后一層上面麸折,比方說(shuō)我們這次的全連接層。
Softmax 函式能將某層中的所有神經(jīng)元裡頭的數(shù)字作正規(guī)化(Normalization):將它們?nèi)繅嚎s到 0 到 1 之間的范圍粘昨,并讓它們的和等于 1垢啼。
Softmax 能將多個(gè)數(shù)字作正規(guī)化窜锯,讓它們的值為 1 (圖片來(lái)源)
因?yàn)?/p>
- 所有數(shù)值都位于 0 到 1 之間
- 所有數(shù)值相加等于 1
這兩個(gè)條件恰好是機(jī)率(Probability)的定義,Softmax 函式的運(yùn)算結(jié)果可以讓我們將每個(gè)神經(jīng)元的值解釋為對(duì)應(yīng)分類(Class)的發(fā)生機(jī)率芭析。
以我們的假新聞分類任務(wù)來(lái)說(shuō)的話锚扎,每個(gè)值就各代表以下分類的發(fā)生機(jī)率:
- 不相關(guān): 0.46
- 新聞 B 同意新聞 A:0.34
- 新聞 B 不同意新聞 B:0.20
如果現(xiàn)在是在做預(yù)測(cè)且我們只能選出一個(gè)分類當(dāng)作答案的話,我們可以說(shuō)這次的分類結(jié)果最有可能是「不相關(guān)」這個(gè)類別馁启,因?yàn)槠浒l(fā)生機(jī)率最高驾孔。
在定義好模型以后,我們就可以進(jìn)入下個(gè)步驟:定義衡量模型好壞的指標(biāo)进统。
決定如何衡量模型的表現(xiàn)
為了讓機(jī)器自動(dòng)「學(xué)習(xí)」,我們得給它一個(gè)損失函數(shù)(Loss Function)浪听。
給定一個(gè)正確解答 y
以及模型預(yù)測(cè)的結(jié)果 y_head
螟碎,我們的模型透過(guò)損失函數(shù)就能自動(dòng)計(jì)算出現(xiàn)在的預(yù)測(cè)結(jié)果跟正解的差距為多少。
透過(guò)損失函數(shù)的回饋迹栓,模型會(huì)盡全力修正參數(shù)掉分,以期將此損失函數(shù)的值下降到最低(也就是讓預(yù)測(cè)結(jié)果 y_head
跟正解 y
越來(lái)越接近)。
圖中的拋物線即為損失函數(shù) J(w)克伊。當(dāng)參數(shù) w 有不同值時(shí)酥郭,損失函數(shù)的值也有所不同。模型會(huì)持續(xù)修正參數(shù) w 以期最小化損失函數(shù) (圖片來(lái)源)
那你會(huì)問(wèn)愿吹,在假新聞分類裡頭不从,我們應(yīng)該使用什麼損失函數(shù)呢?
我們?cè)?a target="_blank">將正解做 One-hot Encoding 一節(jié)有稍微提到犁跪,我們會(huì)希望
- 正確的分類的機(jī)率分佈 P1(例:
[1, 0, 0]
) - 模型預(yù)測(cè)出的機(jī)率分佈 P2(例:
[0.7, 0.2, 0.1]
)
這 2 個(gè)機(jī)率分佈的「差距」越小越好椿息。而能計(jì)算 2 個(gè)機(jī)率分佈之間的差距的交叉熵(Cross Entropy)就是這次的分類問(wèn)題中最適合的損失函數(shù)。
交叉熵能幫我們計(jì)算兩個(gè)機(jī)率分佈的差距坷衍,適合作為分類問(wèn)題的損失函數(shù) (圖片來(lái)源)
在 Keras 里頭寝优,我們可以這樣定義模型的損失函數(shù):
model.compile( optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
categorical_crossentropy
即是我們剛剛所說(shuō)的交叉熵,而 accuracy
則是準(zhǔn)確度枫耳,會(huì)被我們用來(lái)在訓(xùn)練過(guò)程中了解模型的表現(xiàn)情況乏矾。
精準(zhǔn)度的定義為:
雖然有了交叉熵來(lái)當(dāng)作我們模型的損失函數(shù),但是實(shí)際上模型要如何更新裡頭的參數(shù)呢迁杨?我們需要一個(gè)優(yōu)化器(Optimizer)來(lái)做到這件事情钻心。
不同優(yōu)化器透過(guò)調(diào)整參數(shù)來(lái)降低損失函數(shù)的情形,就像是在想辦法往溜滑梯的低處滑一樣 (圖片來(lái)源)
雖然我們有很多種優(yōu)化器铅协,但它們基本上都是從梯度下降法(Gradient Descent)延伸而來(lái)扔役。
在上圖的不同位置,梯度下降法會(huì)重新計(jì)算每個(gè)參數(shù)對(duì)損失函數(shù)的梯度(斜率)警医。接著梯度下降法會(huì)利用該梯度來(lái)修正參數(shù)亿胸,使得使用新參數(shù)算出來(lái)的損失函數(shù)的值能夠持續(xù)往下降坯钦。
不同優(yōu)化器則有各自往下滑的秘方,比方說(shuō)自動(dòng)調(diào)整 Learning rate侈玄。
現(xiàn)在就先讓我們使用 RMSProp 優(yōu)化器婉刀。而在有了損失函數(shù)以及優(yōu)化器以后,我們就可以正式開(kāi)始訓(xùn)練模型了序仙!
訓(xùn)練模型并挑選最好的結(jié)果
這步驟很直觀突颊,我們就是實(shí)際使用 model.fit
來(lái)訓(xùn)練剛剛定義出來(lái)的孿生 LSTM 模型:
######## 決定一次要放多少成對(duì)標(biāo)題給模型訓(xùn)練
BATCH_SIZE = 512
######## 決定模型要看整個(gè)訓(xùn)練資料集幾遍
NUM_EPOCHS = 10
######## 實(shí)際訓(xùn)練模型 history = model.fit(
######## 輸入是兩個(gè)長(zhǎng)度為 20 的數(shù)字序列 x=[x1_train, x2_train], y=y_train, batch_size=BATCH_SIZE, epochs=NUM_EPOCHS,
######## 每個(gè) epoch 完后計(jì)算驗(yàn)證資料集
########上的 Loss 以及準(zhǔn)確度 validation_data=( [x1_val, x2_val], y_val ),
######## 每個(gè) epoch 隨機(jī)調(diào)整訓(xùn)練資料集
######## 裡頭的數(shù)據(jù)以讓訓(xùn)練過(guò)程更穩(wěn)定 shuffle=True )
這邊特別值得拿出來(lái)提的是以下兩個(gè)參數(shù):
BATCH_SIZE
NUM_EPOCHS
依照我們前面對(duì)損失函數(shù)(Loss Function)的說(shuō)明,理論上模型是把訓(xùn)練資料集裡頭的 32 萬(wàn)筆資料全部看完一遍之后潘悼,再更新一次參數(shù)以降低損失函數(shù)律秃。
但是這樣太曠日廢時(shí),訓(xùn)練可能要花很久才能完成治唤。
實(shí)務(wù)上都是每次只放入幾筆訓(xùn)練數(shù)據(jù)棒动,讓模型看完這些資料后就做一次參數(shù)的更新。而這個(gè)「幾筆」宾添,就是 BATCH_SIZE
船惨。
依照 BATCH_SIZE
的大小,梯度下降(Gradient Descent, 后稱 GD)可以概括為 3 個(gè)類別:
- GD(
BATCH_SIZE
= 訓(xùn)練資料集大小缕陕,且這時(shí)不稱為 batch) - Mini-batch GD(
BATCH_SIZE
通常為一個(gè)較小的 2 的倍數(shù)) - SGD(
BATCH_SIZE
= 1)
想像損失函數(shù)是個(gè)越往裡面值就越低的碗粱锐,梯度下降就是要想辦法到達(dá)中心點(diǎn) (圖片來(lái)源)
如上圖所示,下方的 GD 因?yàn)樵诿看胃聟?shù)前都會(huì)看完訓(xùn)練資料集裡頭所有的數(shù)據(jù)扛邑,因此它更新參數(shù)的方向是最可靠的怜浅。但要往前走一步就就得看完 32 萬(wàn)筆數(shù)據(jù),未免成本也太大蔬崩。
另一個(gè)極端是上方的 SGD:模型每看完 1 個(gè)訓(xùn)練數(shù)據(jù)就嘗試更新權(quán)重海雪,而因?yàn)閱我灰还P訓(xùn)練數(shù)據(jù)并不能很好地代表整個(gè)訓(xùn)練資料集,前進(jìn)的方向非常不穩(wěn)定舱殿。
隨機(jī)梯度下降(SGD)與 Mini-batch 梯度下降的比較 (圖片來(lái)源)
因此我們常常採(cǎi)用的是中庸之道: Mini-batch GD 的方式來(lái)訓(xùn)練模型奥裸,而這靠的是指定 model.fit
函式裡頭的 batch_size
。
NUM_EPOCHS
則很容易理解:你希望模型不只將 32 萬(wàn)筆的訓(xùn)練數(shù)據(jù)都看過(guò)一遍沪袭,而是每一筆資料還要多看過(guò)好幾次湾宙,以讓模型確確實(shí)實(shí)地從它們身上學(xué)到東西。NUM_EPOCHS
= 10 的意思就代表模型會(huì)重複看整個(gè)訓(xùn)練資料集 10 次冈绊。
接著讓我們看看 Keras 的訓(xùn)練過(guò)程:
利用 Keras 訓(xùn)練神經(jīng)網(wǎng)路的過(guò)程
因?yàn)槟P偷哪繕?biāo)就是要最小化損失函數(shù)(Loss Function)侠鳄,你可以觀察到當(dāng)模型看過(guò)越多訓(xùn)練資料集(Training Set)的數(shù)據(jù)以后,損失值(loss)就越低死宣,分類的準(zhǔn)確度(acc)則越高伟恶。
這代表我們的模型越來(lái)越熟悉訓(xùn)練資料集裡頭的數(shù)據(jù),因此在訓(xùn)練資料集裡頭的表現(xiàn)越來(lái)越好毅该。
如果依照準(zhǔn)確度以及損失值分別畫(huà)圖的話則會(huì)長(zhǎng)這樣:
很明顯地博秫,我們的神經(jīng)網(wǎng)路有過(guò)適(Overfittng)的問(wèn)題:儘管在訓(xùn)練資料集表現(xiàn)得非常好(準(zhǔn)確度超過(guò) 90 %潦牛、損失小于 0.2),在從沒(méi)看過(guò)的驗(yàn)證資料集的表現(xiàn)就相對(duì)遜色不少挡育。且在第 6 個(gè) epoch 之后驗(yàn)證資料集的準(zhǔn)確度 val_acc
就沒(méi)什麼在上升巴碗,驗(yàn)證集的損失 val_loss
則已經(jīng)逐漸上升。
這代表模型利用從訓(xùn)練資料集學(xué)到的模式(Pattern)還無(wú)法非常精準(zhǔn)地預(yù)測(cè)沒(méi)見(jiàn)過(guò)的事物即寒。
用 Keras 來(lái)實(shí)作深度學(xué)習(xí)的基本 3 步驟
如同我們?cè)?a target="_blank">這章節(jié)一開(kāi)頭所說(shuō)的橡淆,雖然第 3 步驟:「訓(xùn)練模型并挑選最好的結(jié)果」的 Keras 實(shí)作非常簡(jiǎn)單(基本上就是 model.fit( ...)
),但實(shí)際上在一個(gè)機(jī)器學(xué)習(xí) / 深度學(xué)習(xí)專案裡頭母赵,你將會(huì)花 80 % 的時(shí)間在這個(gè)步驟裡頭調(diào)整參數(shù)逸爵,想辦法找到一個(gè)最棒的模型。
儘管如此凹嘲,我們現(xiàn)在最想知道的還是這個(gè)模型在真實(shí)世界(也就是測(cè)試資料集)到底能表現(xiàn)多好师倔,因此先讓我們?cè)囍眠@個(gè)簡(jiǎn)單模型來(lái)做預(yù)測(cè)吧!
進(jìn)行預(yù)測(cè)并提交結(jié)果
就跟我們對(duì)訓(xùn)練 / 驗(yàn)證資料集做的資料前處理一樣施绎,要對(duì)測(cè)試資料集(Test Set)做預(yù)測(cè)溯革,我們得先將裡頭的文本數(shù)據(jù)通通轉(zhuǎn)換成能夠丟進(jìn)模型的數(shù)字序列資料贞绳。
首先谷醉,讓我們把測(cè)試資料集讀取進(jìn)來(lái):
import pandas as pd test = pd.read_csv( TEST_CSV_PATH, index_col=0) test.head(3)
tid1 | tid2 | title1_zh | title2_zh | title1_en | title2_en | |
---|---|---|---|---|---|---|
id | ||||||
--- | --- | --- | --- | --- | --- | --- |
321187 | 167562 | 59521 | 薩拉赫人氣爆棚!埃及總統(tǒng)大選未參選獲百萬(wàn)選票 現(xiàn)任總統(tǒng)壓力山大 | 辟謠!里昂官方否認(rèn)費(fèi)基爾加盟利物浦冈闭,難道是價(jià)格沒(méi)談攏俱尼? | egypt 's presidential election failed to win m... | Lyon! Lyon officials have denied that Felipe F... |
321190 | 167564 | 91315 | 薩達(dá)姆被捕后告誡美國(guó)的一句話,發(fā)人深思 | 10大最讓美國(guó)人相信的荒誕謠言萎攒,如蜥蜴人掌控著美國(guó) | A message from Saddam Hussein after he was cap... | The Top 10 Americans believe that the Lizard M... |
321189 | 167563 | 167564 | 薩達(dá)姆此項(xiàng)計(jì)劃沒(méi)有此國(guó)破壞的話遇八,美國(guó)還會(huì)對(duì)伊拉克發(fā)動(dòng)戰(zhàn)爭(zhēng)嗎 | 薩達(dá)姆被捕后告誡美國(guó)的一句話,發(fā)人深思 | Will the United States wage war on Iraq withou... | A message from Saddam Hussein after he was cap... |
測(cè)試資料集跟訓(xùn)練資料集的唯一差別只在沒(méi)有 label
欄位耍休,因此我們只需要將當(dāng)初在資料前處理章節(jié)使用的步驟原封不動(dòng)地套用在測(cè)試資料集即可刃永。
你可以趁機(jī)複習(xí)一下有哪些步驟:
####### 以下步驟分別對(duì)新聞標(biāo)題 A、B 進(jìn)行
####### 文本斷詞
/ Word Segmentation test['title1_tokenized'] = \ test.loc[:, 'title1_zh'] \ .apply(jieba_tokenizer) test['title2_tokenized'] = \ test.loc[:, 'title2_zh'] \ .apply(jieba_tokenizer)
######## 將詞彙序列轉(zhuǎn)為索引數(shù)字的序列
x1_test = tokenizer \ .texts_to_sequences( test.title1_tokenized) x2_test = tokenizer \ .texts_to_sequences( test.title2_tokenized) # 為數(shù)字序列加入 zero padding x1_test = keras \ .preprocessing \ .sequence \ .pad_sequences( x1_test, maxlen=MAX_SEQUENCE_LENGTH) x2_test = keras \ .preprocessing \ .sequence \ .pad_sequences( x2_test, maxlen=MAX_SEQUENCE_LENGTH)
######## 利用已訓(xùn)練的模型做預(yù)測(cè)
predictions = model.predict( [x1_test, x2_test])
這些步驟現(xiàn)在對(duì)你來(lái)說(shuō)應(yīng)該都已經(jīng)不再陌生羊精。
讓我們看一下從模型得到的預(yù)測(cè)結(jié)果長(zhǎng)什麼樣子:
predictions[:5]
跟我們之前討論過(guò)的一樣斯够,模型針對(duì)每一筆成對(duì)新聞標(biāo)題的輸入,會(huì)回傳給我們 3 個(gè)分類的機(jī)率值喧锦。
現(xiàn)在读规,我們只要將機(jī)率值最大的類別當(dāng)作答案,并將這個(gè)結(jié)果轉(zhuǎn)回對(duì)應(yīng)的文本標(biāo)籤即可上傳到 Kaggle:
index_to_label = {v: k for k, v in label_to_index.items()} test['Category'] = [index_to_label[idx] for idx in np.argmax(predictions, axis=1)] submission = test \ .loc[:, ['Category']] \ .reset_index() submission.columns = ['Id', 'Category'] submission.head()
得到上面的 DataFrame 以后燃少,我們可以將其儲(chǔ)存成 CSV 并上傳到 kaggle束亏,而結(jié)果如下:
我們的 NLP 模型第一次的結(jié)果
如果你還記得我們?cè)?a target="_blank">用直覺(jué)找出第一條底線的章節(jié)內(nèi)容的話,就會(huì)知道這并不是應(yīng)該多好的預(yù)測(cè)結(jié)果阵具,但的確比多數(shù)票決好了一點(diǎn)點(diǎn)碍遍。
不過(guò)不需要操之過(guò)急定铜,因?yàn)槿魏螜C(jī)器學(xué)習(xí)專案都是一個(gè)持續(xù)重複改善的迴圈。在第一次預(yù)測(cè)就做出完美結(jié)果的情況很少雀久,重點(diǎn)是持續(xù)改善宿稀。
在第一次提交結(jié)果以后,我們還可以做非常多事情來(lái)嘗試改善模型效能:
- 改變字典詞彙量赖捌、序列長(zhǎng)度
- 改變?cè)~向量的維度
- 嘗試預(yù)先訓(xùn)練的詞向量如 ELMo祝沸、GloVe
- 調(diào)整 LSTM 層的輸出維度
- 使用不同優(yōu)化器、調(diào)整 Learning rate
- 改變神經(jīng)網(wǎng)路架構(gòu)如使用 GRU 層
- ...
能改善準(zhǔn)確度的方式不少越庇,但因?yàn)闋可娣秶珡V罩锐,請(qǐng)容許我把它們留給你當(dāng)做回家作業(yè)。
走到這裡代表你已經(jīng)完整地經(jīng)歷了一個(gè) NLP 專案所需要的大部分步驟卤唉。在下一節(jié).讓我們回顧一下在這趟旅程中你所學(xué)到的東西涩惑。
我們是怎麼走到這裡的
在這趟 NLP 旅程里頭,我們學(xué)會(huì)了不少東西桑驱。
現(xiàn)在的你應(yīng)該已經(jīng)了解:
- NLP 中常見(jiàn)的數(shù)據(jù)前處理以及實(shí)踐方法
- 詞向量以及詞嵌入的基本概念
- 神經(jīng)網(wǎng)路常見(jiàn)的元件如全連接層竭恬、簡(jiǎn)單 RNN 以及 LSTM
- 能讀多個(gè)資料來(lái)源的孿生神經(jīng)網(wǎng)路架構(gòu)
- 如何用 Keras 建構(gòu)一個(gè)完整的神經(jīng)網(wǎng)路
- 深度學(xué)習(xí) 3 步驟:建模、定義衡量指標(biāo)以及訓(xùn)練模型
- 梯度下降熬的、優(yōu)化器以及交叉熵等基本概念
- 如何利用已訓(xùn)練模型對(duì)新數(shù)據(jù)做預(yù)測(cè)
呼痊硕,這可真了不起,值得慶祝押框!
能閱讀到這裡岔绸,我相信你對(duì)深度學(xué)習(xí)以及 NLP 領(lǐng)域是抱著不少興趣的。而為了讓你在閱讀本文以后能夠繼續(xù)探索這個(gè)世界橡伞,在下一章節(jié)我則會(huì)介紹 3 門(mén)非常推薦的線上課程盒揉。
最后,我則會(huì)在文末總結(jié)一下自己的心得兑徘。
現(xiàn)在刚盈,先看看有哪些課程吧!
3 門(mén)推薦的線上課程
為了奠定 NLP 的基礎(chǔ)挂脑,這一個(gè)月我一邊複習(xí)舊教材藕漱,一邊看了不少教學(xué)文章以及線上課程。
截至目前最域,我認(rèn)為有 3 個(gè) CP 值十分高的課程值得推薦給你:
- 臺(tái)大電機(jī)系李宏毅教授的深度學(xué)習(xí)課程
- 奠定理論基礎(chǔ)
- Coursera 的 Deep Learning 專項(xiàng)課程
- 理論 70 % + 實(shí)作 30 %
-
Deep Learning with Python
- 注重程式實(shí)作
這邊說(shuō)的 CP 值高(對(duì)谴分,我知道你最愛(ài) CP 值)指的是能用最少的時(shí)間、精力以及金錢(qián)來(lái)確確實(shí)實(shí)地學(xué)好 NLP 的理論及實(shí)作基礎(chǔ)镀脂。
李宏毅教授的 Youtube 播放清單 (圖片來(lái)源)
李宏毅教授的機(jī)器學(xué)習(xí)課程內(nèi)行的都知道牺蹄,大概是全世界最好、最完整的 Deep Learning 中文學(xué)習(xí)資源薄翅。李教授在課程中廣徵博引學(xué)術(shù)論文沙兰,但卻同時(shí)非常淺顯易懂氓奈。你可以在這邊看到教授所有的 Youtube 課程播放清單。
就我所知鼎天,教授在臺(tái)大上課很注重實(shí)作舀奶,有不少作業(yè)需要完成,但因?yàn)榫€上只有影片可以查看斋射,因此我將其分類為「奠定理論基礎(chǔ)」育勺。
Deep Learning Specialization (圖片來(lái)源)
原 Google Brain 的吳恩達(dá)教授的 Deep Learning 專項(xiàng)課程則是 Coursera 上最受歡迎的深度學(xué)習(xí)課程。跟我們這篇文章最相關(guān)的 NLP 技術(shù)則被涵蓋在該專項(xiàng)課程的最后一堂課:Sequence Models罗岖。
我在大約一年前完成包含卷積神經(jīng)網(wǎng)路 CNN 的前四堂課涧至,而因?yàn)檎n程上線已有一段時(shí)間,現(xiàn)在影片大都有簡(jiǎn)體或繁體中文的字幕桑包,不太需要煩惱聽(tīng)不懂英文南蓬。
Deep Learning with Python Video Edition 的作者 Fran?ois Chollet 為軟體工程師出身,設(shè)計(jì)出知名深度學(xué)習(xí)框架 Keras哑了,目前則在 Google AI 工作赘方。
該書(shū)以 Programmer 的角度出發(fā),提供了利用 Keras 實(shí)現(xiàn)各種 NLP 任務(wù)的范例弱左,十分適合在熟悉深度學(xué)習(xí)理論后想要實(shí)作的人閱讀窄陡。
就算你不想花錢(qián)買(mǎi)書(shū)或是訂閱 O'Relly Online,你也可以在他有 5,000 多顆星的 Github Repo deep-learning-with-python-notebooks 看到跟該課程相關(guān)的所有 Jupyter Notebooks科贬。
這些課程可以說(shuō)是幫助我完成這篇文章以及 Kaggle 競(jìng)賽的最大功臣泳梆,而我也希望能透過(guò)這篇文章的微薄之力讓你知道他們的存在鳖悠,并隨著他們繼續(xù)你從這里開(kāi)始的 NLP 探險(xiǎn)榜掌。
當(dāng)然,除了以上 3 堂課程乘综,你還可以在由淺入深的深度學(xué)習(xí)資源整理一文看到更多我整理的深度學(xué)習(xí)資源憎账。你也可以直接前往 Github Repo 查看。
結(jié)語(yǔ):從掌握基礎(chǔ)到運(yùn)用巨人之力
網(wǎng)路上多的是專業(yè)的 NLP 教學(xué)文章或論文探討卡辰,但平易近人的中文文章卻少之又少胞皱。
在文章開(kāi)頭我說(shuō):
希望這篇文章能成為你前往自然語(yǔ)言處理世界的最佳橋樑。
這野心聽(tīng)起來(lái)很狂妄九妈,但至少我已經(jīng)嘗試用最平易近人的詞彙向你介紹這個(gè) NLP 世界的一丁點(diǎn)基礎(chǔ)知識(shí)反砌,而我也希望你真的學(xué)到了些什麼、獲得些啟發(fā)萌朱。
現(xiàn)在深度學(xué)習(xí)以及 NLP 領(lǐng)域?qū)嵲诎l(fā)展太快宴树,就算一個(gè)人有興趣也常常不知從何開(kāi)始學(xué)起。
事實(shí)上晶疼,NLP 的發(fā)展速度還在加快酒贬,而這既是好消息也是壞消息又憨。
NLP 如果是輛衝往未來(lái)的火車的話,深度學(xué)習(xí)就是它的引擎锭吨,而我們的數(shù)據(jù)是它的燃料蠢莺。另外,多數(shù)人還沒(méi)有登上這臺(tái)火車
這邊說(shuō)的 NLP零如,其實(shí)更適合用人工智慧取代躏将。
對(duì)還沒(méi)掌握機(jī)器學(xué)習(xí) / 深度學(xué)習(xí) / NLP 知識(shí)的人來(lái)說(shuō),這些技術(shù)只會(huì)離自己越來(lái)越遠(yuǎn)考蕾,最后遠(yuǎn)到只會(huì)在新聞報(bào)導(dǎo)或科幻小說(shuō)上看到耸携,儘管被這些技術(shù)驅(qū)動(dòng)的龐大系統(tǒng)每天影響著他們的生活。
至于那些已經(jīng)掌握這些知識(shí)的人辕翰,透過(guò)運(yùn)用如遷移學(xué)習(xí)等巨人之力夺衍,就連一般人也能做到以前憑自己力量做不到的事情。
比方說(shuō)利用 Google 在今年 11 月公開(kāi)的龐大語(yǔ)言代表模型 BERT喜命,我不費(fèi)吹灰之力就在本文的 Kaggle 競(jìng)賽達(dá)到 85 % 的正確率沟沙,距離第一名 3 %,總排名前 30 %壁榕。
我們之前設(shè)計(jì)的 LSTM 模型則僅有 67 % 準(zhǔn)確度矛紫。
并不是說(shuō)只要用新的語(yǔ)言代表模型就好,這篇學(xué)的東西都不重要牌里。事實(shí)上正好相反:正是因?yàn)橛辛舜似?NLP 基礎(chǔ)知識(shí)颊咬,才讓我得以順利地運(yùn)用該巨人之力。如果你有興趣深入了解牡辽,可以接著閱讀進(jìn)擊的 BERT:NLP 界的巨人之力與遷移學(xué)習(xí)喳篇,用最直觀的方式理解并實(shí)際運(yùn)用這個(gè)巨人之力。
BERT 是在 NLP 領(lǐng)域裡家喻戶曉的語(yǔ)言代表模型 (圖片來(lái)源)
深度學(xué)習(xí)以及 NLP 領(lǐng)域發(fā)展快速态辛,但你總要從某個(gè)地方開(kāi)始好好地學(xué)習(xí)基礎(chǔ)麸澜,而且越快開(kāi)始越好。
所以我留給你的最后一個(gè)問(wèn)題就是:
你奏黑,打算什麼時(shí)候出發(fā)炊邦?