手把手:自然語言處理太難?按這個套路走,就是砍瓜切菜!(附Python程式碼)...

weixin_34007291發表於2018-02-28

10137682-435ce3a2df276c82
image

大資料文摘作品

編譯:****小飯盆、****周佳玉、****笪潔瓊、錢****天培

豆瓣水軍檢測、《權遊》續寫、越來越神的谷歌翻譯......

最近自然語言處理(NLP)的各路應用可是被玩得風生水起。

這些NLP應用看起來炫酷到沒道理,但其實背後的原理並不難理解。

今天,文摘菌就來扒一扒最常用的自然語言處理技巧和模型,手把手教你做一個簡單神奇的小應用。

不吹不黑,90%的NLP問題都能用類似方法解決。

今天這個教程從資料處理的三大階段教你自然語言處理:

  • 收集,準備、檢查資料

  • 建立簡單的模型(包括深度學習模型)

  • 解釋、理解你的模型

整篇教程的Python程式碼都在這兒啦:

https://github.com/hundredblocks/concrete_NLP_tutorial/blob/master/NLP_notebook.ipynb

趕緊開始吧!

第1步:收集資料

自然語言資料的來源太多啦!淘寶評論、微博、百度百科等等。

不過今天呢,我們要處理的資料集來自推特“社交媒體上的災難”資料集(Disasters on Social Media dataset)。

我們將使用由CrowdFlower慷慨提供的一個名為“社交媒體災難”的資料集。該資料集由一萬多條與災難有關的推特組成。

其中一部分推特確實描述了災難事件,而剩下的則是影評、笑話等等奇怪的東西=。=

我們的任務將是檢測哪些推文是關於一個災難性的事件,而不是一個不相關的話題,如電影。為啥要這麼做呢?有關部門就可以用這個小應用及時得到災難事件資訊了嘛!

接下來,我們將把有關災難的推特稱為“disaster”,並將其他推文稱為“irrelevant”。

Labels標籤

注意哦,我們用的是有標籤的資料。正如NLP大神Socher所說,與其花一個月用無監督學習處理一堆沒有標記過的資料,還不如花個一週時間標記一點資料,整一個分類器。

10137682-21f653003dd87e0f
image

第2步:清洗資料

我們遵循的第一原則是:“再好的模型也拯救不了shi一樣的資料”。所以,先來清洗一下資料吧!

我們做以下處理:

1. 刪除所有不相關的字元,如任何非字母數字字元

2. 通過文字分隔分成單獨的單詞來標記你的文章

3. 刪除不相關的字詞,例如“@”推特或網址

4. 將所有字元轉換為小寫字母,以便將諸如“hello”,“Hello”和“HELLO”等單詞看做相同單詞

5. 考慮整合拼寫錯誤或多種拼寫的單詞,用一個單詞代表(例如“cool”/“kewl”/“cooool”)相結合

6. 考慮詞形還原(把“am”,“are”,“is”等詞語縮小為“be”這樣的常見形式)

按照這些步驟並檢查其他錯誤之後,我們可以開始使用乾淨的標記資料來訓練模型!

第3步:找到一個好的資料表示方式

資料清理完了,我們還得把這些文字轉換成數值——這樣機器才看得懂嘛!

例如,在影象處理中,我們就需要把圖片轉換成一個表示畫素點RGB強度數字矩陣。

10137682-a1595a9e1d030162
image

一個笑臉代表著一個數字矩陣

自然語言處理中的表示稍微複雜一點。我們會嘗試多種表示方法。

獨熱編碼(詞袋)

表示計算機文字的一種自然方法是將每個字元單獨編碼為一個數字(例如ASCII)。

例如,我們可以建立資料集中所有唯一字的詞彙表,並將唯一索引與詞彙表中的每個單詞相關聯。然後,每個句子都被表示為一個與我們詞彙表中唯一字數量一樣長的列表。在這個列表中的每個索引處,我們標記給定詞語出現在我們句子中的次數。這就是所謂的詞袋模型,因為它是一個完全忽略我們句子中單詞順序的表現形式。如下所示。

10137682-a94b4e40f24a5393
image

代表句子作為一個詞袋。左邊為句子,右邊是其表示形式。向量中的每個索引代表一個特定的詞

視覺化嵌入

在“社交媒體的災難”這個例子中,我們有大約2萬字的詞彙,這意味著每個句子都會被表示為一個長度為2萬的向量。該向量將包含大部分0,因為每個句子只包含我們詞彙的一個很小的子集。

為了瞭解我們的表示是否捕獲與我們的問題相關的資訊(即推文是否與災難有關),讓我們將它們視覺化並檢視這些類是否看起來很好地分離是一個好主意。由於詞彙通常非常大,並且不可能在20,000維度上顯示資料,所以像PCA這樣的技術將有助於將資料投影到兩個維度。如圖所示:

10137682-278bd85c425e8a4b
image

視覺化

這兩類看起來不太好分開,這可能是我們嵌入的一個特徵,或者僅僅是由於我們的維度降低。為了看看詞袋特徵是否有用,我們可以根據它們來訓練一個分類器。

第4步:分類

首先遇到問題時,一般的最佳做法是從最簡單的工具開始解決問題。每當涉及到對資料進行分類時,基於通用性和可解釋性的一個普遍喜好是Logistic迴歸。訓練非常簡單,結果可以解釋,因為你可以輕鬆地從模型中提取最重要的係數。

我們將資料分成一個用於擬合模型的訓練集和一個用於評估模型泛化能力的測試集,以此來推廣到不可見的資料。訓練結束後,我們得到了75.4%的準確度。還不錯哦!如果我們簡單地猜測最頻繁的類(“irrelevant”),準確率只能達到57%。但是,即使75%的精度足夠滿足我們的需求,我們也不應該在不嘗試瞭解它的情況下,釋出一個模型。

第5步:檢查

混淆矩陣

第一步是瞭解我們模型的錯誤型別,以及哪種型別的錯誤是最不可取的。在我們的例子中,假陽性劃分為irrelevant,事實上是diasaster,而假陰性實際是disaster,而歸類為irrelevant。如果要優先處理每一個潛在的事件,我們會想要降低我們的假陰性。然而,如果我們受到資源的限制,我們可能會優先考慮較低的假陽性來減少誤報。 將這些資訊視覺化的一個好方法是使用混淆矩陣,它將我們的模型的預測與真實標籤進行比較。理想情況下,矩陣將是從左上角到右下角的對角線(預測和實際完美匹配)。

10137682-6dc0cc100613e306
image

混淆矩陣(綠色是高,藍色是低)

相對於假陽性來說,我們的分類器按比例產生更多的假陰性。換句話說,我們模型最常見的錯誤是將disaster歸類為irrelevant。如果假陽性導致高的執法成本,這使我們的分類器可以有一個很好的bias(偏差)。

模型解析

為了對我們的模型進行驗證並分析它預測的準確性,我們需要看它通過使用哪些詞來做決定,這是十分重要的。如果我們的資料存在偏差,那麼分類器將只能在樣本資料中做出準確預測,而這個模型在現實世界中則不能很好地推廣。在此,我們分別為disaster和irrelevant繪製了“最關鍵的詞”的表。由於我們可以對用於預測的模型的係數進行提取和排序,使用詞袋和邏輯迴歸來計算單詞的重要性其實很簡單。

10137682-da302580d833031f
image

詞袋:關鍵詞

我們的分類器正確地採取了一些模式(如hiroshima廣島、massacre大屠殺),但這其中也顯然有一些看似無意義的過度擬合(heyoo藍調搖滾,x1392話題簡稱)。現在,我們的詞包模型正在處理包含各種不同單詞的巨大詞彙表,並且平等地對待所有單詞。然而,這其中的一些詞語出現的非常頻繁,只會對我們的預測產生影響。接下來,我們將嘗試一種新方法來表示能夠統計單詞頻率的句子,看看能否從我們的資料中獲取更多的訊號。

第6步:統計詞彙結構

為了使我們的模型更多的專注於有意義的單詞,我們可以在詞袋模型頂部使用TF-IDF評分(術語頻率、逆文件頻率)。TF-IDF通過在資料集中的出現頻率來確定詞權重,減少出現過於頻繁的詞的權重而增加到噪音干擾上。下圖是對我們新嵌入資料的PCA預測。

10137682-f32e9bbac5b48cc6
image

TF-IDF嵌入視覺化

從上圖可以看出,在這兩種顏色之間有一個相對清晰的分界。這將會使我們的分類器更容易將其分為兩組。讓我們來看看這是否會帶來更好的表現吧!接下來在我們新嵌入的資料上訓練另一個Logistic迴歸引數,我們得到了76.2%的準確性。

這是一個非常細微的改進。我們的模型是否已經開始採用更關鍵的詞?如果我們在防止我們模型“作弊”的同時取得了更好的效果,那麼我們就可以真正認為這個模型實現了一次突破了。

10137682-8251a047338469b0
image

TF-IDF:關鍵詞

模型所採取的詞看起來更相關!儘管我們測試集的指標只是略有增加,但是我們對模型使用的術語將會更有信心,所以將其應用在與客戶互動的系統中會感到更加舒適。

第7步:巧妙利用語義

將詞轉化為向量

我們的最新模型設法採取具有高訊號的詞。然而,如果我們配置這個模型,很可能會遇到我們之前在訓練集中沒有看到的詞。然而即使在訓練中看到非常相似的單詞,以前的模型也不能準確辨別這些干擾。

為了解決這個問題,我們需要捕捉詞的語義,這意味著我們需要理解“好”和“積極”等詞比“杏”和“大陸”更相近。我們將用名為Word2Vec這個工具幫助我們捕捉語義。

使用預訓練的詞

Word2Vec是一種實現連續詞嵌入的技術。它通過閱讀大量的文字來學習,並記憶哪些詞傾向於出現在相似的語境中。在訓練足夠多的資料後,它會為詞彙表中的每個詞生成一個300維的向量,意思相近的詞彼此則會更接近。

本文的作者開源了一個模型,它在一個非常龐大的語料庫上預先訓練好,我們可以利用這個語料庫將一些語意知識納入到我們的模型中。預訓練的向量可以在與這篇文章相關的知識庫中找到。

句級表示

為我們的分類器獲得句子嵌入的一個快速方法是:平均句中所有詞的Word2Vec得分。這跟以前一樣也是一個詞袋的方法,但是這次我們只丟掉句子的語法,而保留一些語意資訊。

10137682-78023a0f2f33eb8f
image

Word2Vec句嵌入

下圖是使用先前技術獲得的新嵌入視覺化:

10137682-d450b0738ce4c86d
image

Word2Vec嵌入視覺化

兩組顏色的分界看起來更加明顯,我們的新嵌入技術一定能幫助我們的分類器找到兩個類之間的分離。第三次(使用Logistic迴歸)訓練同一個模型後,我們得到了77.7%的精準度,這是我們到目前為止得到的最好的結果!接下來該檢查我們的模型了。

複雜性與可解釋性的權衡

由於新嵌入技術沒有像我們以前的模型那樣以每個單詞一維向量來表示,所以很難看出哪些單詞與我們的分類最為相關。雖然我們仍能使用Logistic迴歸的係數,但它們只與我們嵌入的300維度相關,而與詞彙索引沒有關聯。

對於如此低的準確度,失去所有可解釋性似乎是一個艱難的權衡。然而,對於更復雜的模型,我們可以利用LIME等黑盒直譯器來深入瞭解分類器的工作原理。

Github通過開源軟體包提供LIME。黑盒直譯器允許使用者通過干擾輸入(在我們例子中即去除句子中的單詞)來解釋任何分類器的決定,並檢視預測的變化。

接下來讓我們一起看看我們資料集中的幾個句子的解釋。

10137682-0b3394fe739ed4c3
image
10137682-82cf6c0e67257eea
image

然而,我們並沒有時間去探索資料集中的數千個案例。我們應該做的則是在測試案例的典型範例上繼續執行LIME,看看哪些詞的佔有率仍能位居前列。通過這種方法,我們可以獲得像以前模型那樣的單詞的重要性分數,並驗證模型的預測。

10137682-df0e9797d75bc575
image

Word2Vec:關鍵字

模型似乎能提取高度相關的詞,這意味著它也許能做可理解的決定。而這些看起來像是以前所有模型中最相關的詞,因此我們更願意將其配置到實際操作中。

第8步:使用端到端的方法來巧妙利用語義

我們已經介紹了快速有效的方法來生成緊湊的句嵌入。然而,通過省略詞序,我們放棄了句子的所有句法資訊。如果這些方法不能提供充分的結論,則可使用更復雜的模型,將整個句子作為輸入並預測標籤,而不需要建立中間表示。一種常見的方法是將句子作為一個詞向量序列,使用Word2Vec或更新的方法,如GloVe或CoVe。這就是我們將在下面做的。

10137682-6641aa9eebd6736f
image

高效的端到端體系結構(源)

用於句子分類的卷積神經網路訓練非常迅速,並且作為入門級的深度學習體系能夠很好地完成任務。雖然卷積神經網路(CNN)主要因其在影象資料上的效能而聞名,但它們早已在文字相關任務上提供了優異的結果,並且通常比大多數複雜的NLP方法(例如LSTM和編碼器/解碼器體系結構)能更快地訓練。這個模型保留了詞序,並且學習了關於哪些詞序列可以預測我們目標類的有價值的資訊。與之前的模式相反,它是可以區分“亞歷克斯吃植物”和“植物吃亞歷克斯”的不同。

訓練這個模型不僅不需要比以前方法更多的工作(詳見程式碼),而且給了我們一個比以前方法更好的模型,準確率達到了79.5%!與上述模型一樣,下一步應該是繼續使用我們描述的方法來進行探索和解釋預測,以驗證它確實是配置給使用者的最佳模型。現在,你應該能自己上手處理這個問題了。

小結

  • 從一個簡單快捷的模型開始

  • 解釋其預測

  • 瞭解它正在犯的錯誤型別

  • 利用這些知識來確定下一步工作:模型對資料是否有效,還是應該使用更為複雜的模型

這些方法被應用於特定的案例,如理解和利用諸如推文之類的短文字模型,但實際上這些思想廣泛地適用於各種問題哦!

就像開頭文摘菌說的,90%的自然語言處理問題都可以用這個套路解決,那還不是砍瓜切菜!

原文連結:

https://blog.insightdatascience.com/how-to-solve-90-of-nlp-problems-a-step-by-step-guide-fda605278e4e?gi=6fefa8b6c671

相關文章