當前位置:
首頁 > 知識 > 都說 AllenNLP 好用,我們跑一遍看看究竟多好用

都說 AllenNLP 好用,我們跑一遍看看究竟多好用

本文為雷鋒字幕組編譯的技術博客,原標題Deep Learning for text made easy with AllenNLP,作者為Déborah Mesquita 。

翻譯 | 汪寧 徐瑋 整理 | 凡江

良好學習過程的關鍵原則之一,就是讓學習的內容略高於當前的理解。如果該主題與你已知的內容太過於相似,那麼你就不會有很大的進步。另一方面,如果這個主題太難的話,你就會停滯不前,幾乎沒有進展。

深度學習涉及很多不同的主題和很多我們需要學習的東西,所以一個好的策略就是開始研究人們已經為我們構建好了的東西。這就是為什麼框架非常棒的原因。框架使我們不必太過於關心如何構建模型的細節,使得我們可以更多地關注我們想要完成的任務(而不是專註於如何實現)。

對於構建深度學習中的NLP模型,AllenNLP框架使得任務變得十分有趣。這對我來說是一個驚喜,因為我之前在深度學習中的NLP的學習經歷是痛苦的。

處理NLP任務需要不同類型的神經網路單元,因此在開始學習如何使用AllenNLP框架之前,我們先快速回顧這些單元背後的理論。


當簡單的神經網路不夠時

在簡單的工作中,閱讀文本的任務包括構建我們之前閱讀的內容。舉個例子,如果之前你沒讀過這個句子你可能就不懂這個句子的意思,所以創建這些神經網路單元背後的想法是:

「人類為了理解接下來會發生什麼,把他們以前讀過的東西找出來,也許我們在模型中使用這種機制,他們就能更好地理解文本,對吧?」

遞歸神經網路

為了使用考慮時間的網路,我們需要一種表示時間的方式。但我們如何做到這一點?

處理具有時間範圍的模式的一種顯而易見的方法是通過將模式的序列順序與模式向量的維度相關聯來顯式的表示時間。第一時間事件由模式向量中的第一個元素表示,第二個時間事件由模式向量中的第二個位置表示,依此類推。 -Jeffrey L. Elman

問題是這種方法有幾個缺點,例如:

[...] 移位寄存器對模式的持續時間施加了一個嚴格的限制 (因為輸入層必須提供最長可能的模式),並且建議所有輸入向量具有相同的長度。這些問題在語言等領域特別麻煩,因為在這些領域中,人們希望具有可變長度模式的類似表示。語言的基本單位(拼音段)與句子一樣也是如此。

Jeffrey L. Elman討論了論文中發現的其他缺陷。本文介紹了 Elman網路,這是一個三層網路,增加了一組「上下文統一」。

如果你對神經網路完全陌生,那麼閱讀我寫的另一篇文章可能是個好主意。但簡單地說,神經網路是有機會被激活的或者不是被輸入的。

Elman根據Jordan(1986)提出的方法開始他的工作。Jordan引入遞歸連接。

遞歸連接允許網路的隱藏單元看到自己以前的輸出,以便隨後的行為可以被以前的響應所決定。這些遞歸的連接是網路存儲器的功能。緊接著Elman添加了上下文單元。這些上下文單元作為一個時鐘來說明什麼時候我們應該放棄以前的輸入。但是這又如何呢?上下文單元也具有調整權重的機制,就像其他神經網路單元一樣。

上下文單元和輸入激活神經網路隱藏單元。 當神經網路「學習」時,這意味著它有一個表示所有輸入網路處理的模式。上下文單元記住以前的內部狀態。

如果這些都沒有意義,不要擔心。只要想一想,現在我們有一個神經網路單元,它將先前的狀態考慮在內以產生下一個狀態。

「現在我們有一個神經網路單元,它考慮到以前的狀態來產生下一個狀態。」

當 RNNs 不夠時:LSTM

正如Christopher Ola 在另一篇文章解釋的那樣 (如果你想了解更多關於LSTM的信息,這篇文章是很棒的),有時我們需要更多的上下文,也就是有時我們需要存儲很久以前看到的信息。

考慮嘗試預測「我在法國長大......我會說流利的法語 」中的最後一句話。最近的信息表明,下一個詞可能是一種語言的名稱,但如果我們想要縮小到具體是哪種語言,我們需要從法國出發來考慮更長遠的東西。縮小相關信息與需要變得非常大的點之間的差距完全可能 -Christopher Ola

LSTM單元解決了這個問題。它們是一種特殊的RNN,能夠學習長期的依賴關係。我們將只使用LSTM單元,而不是構建它們,因此對於我們而言,可以將LSTM單元看作具有不同架構並能夠學習長期依賴性的單元。


構建一個文本分類的高級模型

好了,有了足夠的理論,現在讓我們進入有趣的部分,並建立模型。

訓練過程

上面的圖片向我們展示了我們如何設置一切。首先我們得到數據,然後將它編碼為模型將理解的格式("tokens"和"internal_text_encoder"),然後我們用這些數據來訓練網路,對比標記並調整權重。在這個過程結束時,模型已經準備好做出預測了。

現在我們終於會感受到AllenNLP的魔力!我們將用一個簡單的JSON文件指定上圖中的所有內容。

{

"dataset_reader": {

"type":"20newsgroups"

},

"train_data_path":"train",

"test_data_path":"test",

"evaluate_on_test":true,

"model": {

"type":"20newsgroups_classifier",

"model_text_field_embedder": {

"tokens": {

"type":"embedding",

"pretrained_file":"https://s3-us-west-2.amazonaws.com/allennlp/datasets/glove/glove.6B.100d.txt.gz",

"embedding_dim":100,

"trainable":false

}

},

"internal_text_encoder": {

"type":"lstm",

"bidirectional":true,

"input_size":100,

"hidden_size":100,

"num_layers":1,

"dropout":0.2

},

"classifier_feedforward": {

"input_dim":200,

"num_layers":2,

"hidden_dims": [200,100],

"activations": ["relu","linear"],

"dropout": [0.2,0.0]

}

},

"iterator": {

"type":"bucket",

"sorting_keys": [["text","num_tokens"]],

"batch_size":64

},

"trainer": {

"num_epochs":40,

"patience":3,

"cuda_device":,

"grad_clipping":5.0,

"validation_metric":"+accuracy",

"optimizer": {

"type":"adagrad"

}

}

}

讓我們來看下這段代碼。

1 數據輸入

為了告訴AllenNLP輸入的數據集以及如何讀取它,我們在JSON文件中設置了「dataset_reader」鍵值。

DatasetReader從某個位置讀取數據並構造Dataset。除文件路徑之外的讀取數據所需的所有參數都應

遞給DatasetReader的構造器。 —AllenNLP documentation

數據集是 20個新聞組,我們將在稍後定義如何讀取(在 python 類中)。先來定義模型的其餘部分。

2 模型

我們先設置"model"鍵值來指定模型,在"model"鍵值中還有三個參數:"model_text_field_embedder","internal_text_encoder"和"classifier_feedforward"。

我們先來看一下第一個,其餘的兩個將在稍後說明。

通過"model_text_field_embedder",我們告訴AllenNLP數據在傳遞給模型之前應該如何編碼。 簡而言之,我們希望使數據更「有意義」。 背後的想法是這樣的:如果可以像比較數字那樣比較文字會怎麼樣?

如果5 - 3 + 2 = 4 , 國王-男人+女人=女王,又何嘗不對呢?

用詞嵌入我們可以做到這一點。 這對模型也很有用,因為現在我們不需要使用很多稀疏數組(具有很多零的數組)作為輸入。

詞嵌入是自然語言處理(NLP)中的一組語言建模和特徵學習技術的總稱,其中來自辭彙表的單詞或短語被映射為實數向量。 從概念上講,它涉及從每個單詞一個維度的空間到具有更低維度的連續向量空間的數學嵌入。—Wikipedia

在我們的模型中將使用GloVe:用於辭彙表徵的全局向量。

GloVe是一種用於獲取單詞向量表徵的無監督學習演算法。 對來自語料庫的匯總的全局單詞共現統計進行訓練,表徵結果展示了單詞向量空間的有趣的線性子結構。—Glove

如果還是難以理解,只要將Glove看作是一種將單詞編碼為向量的模型。我們將每個嵌入向量的大小設置為100。

Glove把單詞編碼為向量

這就是"model_text_field_embedder"所做的。

3 數據迭代器

像往常一樣,我們將分批分離訓練數據。 AllenNLP提供了一個名為BucketIterator的迭代器,通過對每批最大輸入長度填充批量,使計算(填充)更高效。 要做到這一點,它將按照每個文本中的符號數對實例進行排序。 我們在"iterator"鍵值中設置這些參數。

4 訓練器

最後一步是設置訓練階段的配置。 訓練器使用AdaGrad優化器作10代訓練,如果最後3代的驗證準確性沒有提高,則停止。

為了訓練模型,我們只需要運行:

python run.py our_classifier.json -s /tmp/your_output_dir_here

另一個很酷的事情是,通過框架我們可以停止並在稍後恢復訓練。 但在此之前,我們需要指定dataset_reader和模型python類。


編寫 AllenNLP Python 類

dataset_reader.py

我們將使用scikit-learn提供的20個新聞組。 為了引用JSON文件中的DatasetReader,我們需要註冊它:

@DatasetReader.register("20newsgroups")

class NewsgroupsDatasetReader(DatasetReader):

你將實施三種方法:其中兩個為read()和text_to_instance()。

read()

read()從scikit-learn獲取數據。通過AllenNLP,你可以設置數據文件的路徑(例如JSON文件的路徑),但在我們的例子中,我們只需像Python模塊一樣導入數據。 我們將讀取數據集中的每個文本和每個標籤,並用text_to_instance()包裝它。

text_to_instance()

此方法「進行任何符號化或必要的處理,來把文本輸入轉為Instance」(AllenNLP Documentation)。在我們的實例中意味著這樣做:

@overrides

def text_to_instance(self, newsgroups_post: str, label: str = None) -> Instance:

tokenized_text = self._tokenizer.tokenize(newsgroups_post)

post_field =

fields = {"post": post_field}

if label is not None:

fields["label"] =

return Instance(fields)

我們將來自20個新聞組的文本和標籤包裝到TextField和LabelField中。

model.py

我們將使用雙向LSTM網路,該網路是第一個循環層被複制的單元。 一層按原樣接收輸入,另一層接收輸入序列的反向副本。 因此,BLSTM網路被設計為捕獲順序數據集的信息並保持過去和未來的上下文特徵。 (來源:中文分詞雙向LSTM循環神經網路)

首先我們來定義模型的類參數

vocab

因為在你的模型中經常會有幾種不同的映射,所以Vocabulary會追蹤不同的命名空間。 在這種情況下,我們為文本設置了「符號」辭彙(代碼中未顯示,是在背後使用的默認值),以及我們試圖預測的標籤的「標籤」辭彙。—— Using AllenNLP in your Project)

model_text_field_embedder

用於嵌入符號與作為輸入的TextField。 返回單詞的 Glove向量表徵。

internal_text_encoder

我們用來把輸入文本轉換為單個向量的編碼器(RNNs,還記得嗎?)。 Seq2VecEncoder是一個模塊,它將一個向量序列作為輸入並返回一個向量。

num_classes — 要預測的標籤數量

現在我們來實現模型類的方法

forward()

前向法做的是

模型所做的第一件事是嵌入文本,然後將其編碼為單個矢量。 為了對文本進行編碼,我們需要獲得掩碼來表示符號序列的哪些元素僅用於填充。

然後,將它經過前饋網路以獲得類別邏輯回歸。 將邏輯回歸經過softmax來獲得預測概率。 最後,如果我們獲得了標籤,我們可以計算損失並評估我們的度量。—Using AllenNLP in your Project

正向法基本上是在做模型訓練任務。 如果你想多了解一些,可以看這個。現在我們來談談模型類參數的一個重要部分:classifier_feedforward。

我們需要Model.forward來計算損失。 訓練代碼將查找由forward返回的字典中的損失值,並計算該損失的梯度以更新模型的參數。—Using AllenNLP in your

decode()

decode有兩個功能:它接收forward的輸出,並對其進行任何必要的推理或解碼,並將整數轉換為字元串以使其便於人類閱讀(例如,用於演示)。—Using AllenNLP in your


運行代碼

正如我之前所說,通過命令行來訓練模型,可以使用以下命令:

python run.py our_classifier.json -s /tmp/your_output_dir_here

我還創建了一個筆記本,以便我們可以在Google Colaboratory上運行實驗並免費使用GPU,以下是鏈接:https://colab.research.google.com/drive/1q3b5HAkcjYsVd6yhrwnxL2ByqGK08jhQ

你也可以在這查看代碼:this repository

我們建立了一個簡單的分類模型,但可能性是無限的。 該框架是為我們的產品創建奇特的深度學習模型的絕佳工具。

博客原址http://deborahmesquita.com/2018-03-19/deep-learning-for-text-made-easy-with-allennlp-62bc79d41f31

更多文章,關注雷鋒網(公眾號:雷鋒網)

添加雷鋒字幕組微信號(leiphonefansub)為好友

備註「我要加入」,To be an AI Volunteer !

4 月 AI 求職季

8 大明星企業

10 場分享盛宴

20 小時獨門秘籍

4.10-4.19,我們準時相約!

新人福利

關注 AI 研習社(okweiwu),回復1領取

【超過 1000G 神經網路 / AI / 大數據資料】

如何在 NLP 領域干成第一件事?


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 AI研習社 的精彩文章:

真實全景圖像強化學習 AI 平台——Matterport3DSimulator
用Pytorch 實現的 Capsule Network

TAG:AI研習社 |