專知-PyTorch手把手深度學習教程07
Practical PyTorch: 用字符集RNN進行名稱分類
本文翻譯自spro/practical-pytorch
原文:https://github.com/spro/practical-pytorch/blob/master/char-rnn-classification/char-rnn-classification.ipynb
翻譯: Mandy
輔助: huaiwen
初始
我們將建立和訓練一個基本的字元級RNN來分類單詞。字元級RNN將字作為一系列字元讀入 - 在每個步驟輸出預測和「隱藏狀態」,將其先前的隱藏狀態饋送到每個下一步驟。我們將最終預測作為輸出,即該詞屬於哪一類。具體來說,我們將從18種語言的起源開始列出數千個姓氏,並根據拼寫預測該名字來源於哪種語言:
舉例:
推薦閱讀
假設你至少安裝了PyTorch,知道Python,並了解Tensors:
http://pytorch.org/ ( 有關安裝說明的網址)
Deep Learning with PyTorch: A 60-minute Blitz (這個鏈接讓你大致了解什麼是PyTorch )
jcjohnson s PyTorch examples ( 深入了解PyTorch )
Introduction to PyTorch for former Torchies ( 如果你之前用過 Lua Torch )
知道並了解RNNs 以及它們是如何工作的是很有用的
The Unreasonable Effectiveness of Recurrent Neural Networks ( 展示了一堆現實生活中的例子)
Understanding LSTM Networks(是關於LSTM具體的,但也是關於RNN的一般介紹)
準備數據
包含在data/names目錄中的是18個文本文件,名稱為「[Language] .txt」。每個文件包含一堆名稱,每行一個名稱,主要是羅馬字體化的(但是我們仍然需要從Unicode轉換為ASCII)。
我們最終會得到一個每種語言名稱列表的字典,。通用變數「category」和「line」(在我們的例子中用於語言和名稱)用於後續的可擴展性。
[ ../data/names/Arabic.txt , ../data/names/Chinese.txt , ../data/names/Czech.txt , ../data/names/Dutch.txt , ../data/names/English.txt , ../data/names/French.txt , ../data/names/German.txt , ../data/names/Greek.txt , ../data/names/Irish.txt , ../data/names/Italian.txt , ../data/names/Japanese.txt , ../data/names/Korean.txt , ../data/names/Polish.txt , ../data/names/Portuguese.txt , ../data/names/Russian.txt , ../data/names/Scottish.txt , ../data/names/Spanish.txt , ../data/names/Vietnamese.txt ]
Slusarski
n_categories = 18
現在我們有category_lines,一個將每個類別(語言)映射到行 列表(名稱)的字典。我們還跟蹤所有類別(只是一個語言列表)和n_categories以供以後參考。
[ Abandonato , Abatangelo , Abatantuono , Abate , Abategiovanni ]
把名字變成Tensors
現在我們已經組織了所有的名字,我們需要把它們變成Tensors來使用它們。
為了表示單個字母,我們使用大小為的「one-hot vector」。一個熱向量填充0,除了當前字母的索引1,例如「b」= 。
為了表達我們的意思,我們將一大堆加入到2維矩陣中。
這個額外的1維是因為PyTorch假設一切都是批量的 -我們只是在這裡使用批量大小為1。
Columns 0 to 12
0 0 0 0 0 0 0 0 0 0 0 0 0
Columns 13 to 25
0 0 0 0 0 0 0 0 0 0 0 0 0
Columns 26 to 38
0 0 0 0 0 0 0 0 0 1 0 0 0
Columns 39 to 51
0 0 0 0 0 0 0 0 0 0 0 0 0
Columns 52 to 56
0 0 0 0 0
[torch.FloatTensor of size 1x57]
torch.Size([5, 1, 57])
創建網路
在自動格式化之前,在Torch中創建一個循環神經網路涉及到克隆了多個時間步長的層的參數。這些層保持隱藏的狀態和漸變,現在完全由圖形本身處理。這意味著你可以以非常「純凈」的方式實施RNN,作為正常的前饋層。
這個RNN模塊(大部分來自PyTorch for Torch用戶教程的複製)只是2個線性層,它們在輸入和隱藏狀態下運行,輸出後面有LogSoftmax層。
手動測試網路
定義了我們定製的RNN類,我們可以創建一個新的實例:
為了開始運行這個網路,我們需要傳遞一個輸入(在我們的例子中是當前字母的Tensor)和一個先前的隱藏狀態(我們首先初始化為零)。我們將取回輸出(每種語言的概率)和下一個隱藏狀態(我們為下一步保留)。
請記住,PyTorch模塊在變數上運行,而不是直接在Tensors。
output.size = torch.Size([1, 18])
為了提高效率,我們不希望為每個步驟創建一個新的Tensor,所以我們將使用line_to_tensor而不是letter_to_tensor並使用slice。這可以通過預先計算批量的Tensors進一步優化。
Variable containing:
Columns 0 to 9
-2.8658 -2.8801 -2.7945 -2.9082 -2.8309 -2.9718 -2.9366 -2.9416 -2.7900 -2.8467
Columns 10 to 17
-2.9495 -2.9496 -2.8707 -2.8984 -2.8147 -2.9442 -2.9257 -2.9363
[torch.FloatTensor of size 1x18]
可以看到輸出是 Tensor,其中每個項目都是該類別的可能性(更高的可能性)。
準備訓練
在進行訓練之前,我們應該製造一些功能函數。第一個是解釋網路的輸出,我們知道這是每個類別的可能性。我們可以使用Tensor.topk得到最大值的索引:
( Irish , 8)
我們還需要一個快速的方式來獲得訓練示例(名稱及其語言):
category = Italian / line = Campana
category = Korean / line = Koo
category = Irish / line = Mochan
category = Japanese / line = Kitabatake
category = Vietnamese / line = an
category = Korean / line = Kwak
category = Portuguese / line = Campos
category = Vietnamese / line = Chung
category = Japanese / line = Ise
category = Dutch / line = Romijn
訓練網路
現在,訓練這個網路所需要的就是展示一大堆例子,讓它做出猜測,並告訴它是否錯誤。
對於損耗函數nn.NLLLoss是適當的,因為RNN的最後一層是nn.LogSoftmax。
我們還將創建一個「優化器」,根據其梯度更新我們的模型的參數。我們將使用具有低學習率的SGD演算法。
每個訓練循環將會:
創建輸入和目標 tensors
創建一個歸零的初始隱藏狀態
閱讀每個字母和保持下一個字母的隱藏狀態
將最終輸出與目標進行比較
反向傳播
返回輸出值和丟失值
現在我們只需要運行一些例子。由於train函數返回輸出和損失,我們可以列印其猜測,並跟蹤繪製的損失。由於有1000個例子,我們只需列印每一個print_every時間步長,並且得到平均損失。
5000 5% (0m 7s) 2.7940 Neil / Chinese (Irish)
10000 10% (0m 14s) 2.7166 O Kelly / English (Irish)
15000 15% (0m 23s) 1.1694 Vescovi / Italian
20000 20% (0m 31s) 2.1433 Mikhailjants / Greek (Russian)
25000 25% (0m 40s) 2.0299 Planick / Russian (Czech)
30000 30% (0m 48s) 1.9862 Cabral / French (Portuguese)
35000 35% (0m 55s) 1.5634 Espina / Spanish
40000 40% (1m 5s) 3.8602 MaxaB / Arabic (Czech)
45000 45% (1m 13s) 3.5599 Sandoval / Dutch (Spanish)
50000 50% (1m 20s) 1.3855 Brown / Scottish
55000 55% (1m 27s) 1.6269 Reid / French (Scottish)
60000 60% (1m 35s) 0.4495 Kijek / Polish
65000 65% (1m 43s) 1.0269 Young / Scottish
70000 70% (1m 50s) 1.9761 Fischer / English (German)
75000 75% (1m 57s) 0.7915 Rudaski / Polish
80000 80% (2m 5s) 1.7026 Farina / Portuguese (Italian)
85000 85% (2m 12s) 0.1878 Bakkarevich / Russian
90000 90% (2m 19s) 0.1211 Pasternack / Polish
95000 95% (2m 25s) 0.6084 Otani / Japanese
100000 100% (2m 33s) 0.2713 Alesini / Italian
繪製結果
從 all_losses變數繪製的歷史數據圖展示網路學習:
[]
評估結果
要了解網路在不同類別上的運行情況,我們將創建一個混淆矩陣,表示對於每種實際語言(行),網路預測為哪種語言(列)的信息。(每一行表示這一類的數據在不同類別上的預測結果)
你可以從主軸上選出亮點,顯示哪些語言預測錯誤,例如很多漢語被預測為韓語這一類了,西班牙語被預測為義大利語。由這個圖可知,希臘語預測的結果非常好,顏色最亮,英語預測的很差(可能的原因是和其他很多歐洲語言有很多重合的詞)
在用戶輸入端運行
Dovesky
(-0.87) Czech
(-0.88) Russian
(-2.44) Polish
Jackson
(-0.74) Scottish
(-2.03) English
(-2.21) Polish
Satoshi
(-0.77) Arabic
(-1.35) Japanese
(-1.81) Polish
Practical PyTorch repo中腳本的最終版本將上述代碼分成幾個文件:
data.py (loads files)
model.py (defines the RNN)
train.py (runs training)
predict.py (runs predict() with command line arguments)
server.py (serve prediction as a JSON API with bottle.py)
運行train.py來訓練並保存網路。
運行具有名稱的predict.py來查看預測:
運行server.py並訪問http://localhost:5533 /Yourname 以獲得JSON輸出的預測。
明天繼續推出:專知PyTorch深度學習教程系列< NLP系列(三) 基於字元級RNN的姓名生成 >,敬請關注。
完整系列搜索查看,請PC登錄
對PyTorch教程感興趣的同學,歡迎進入我們的專知PyTorch主題群一起交流、學習、討論,掃一掃如下群二維碼即可進入:
了解使用專知-獲取更多AI知識!
-END-
專 · 知
關注我們的公眾號,獲取最新關於專知以及人工智慧的資訊、技術、演算法、深度乾貨等內容。掃一掃下方關注我們的微信公眾號。
TAG:專知 |