如何解決90%的自然語言處理問題:分步指南奉上

機器之心發表於2018-01-29


自然語言處理(NLP)與計算機視覺(CV)一樣,是目前人工智慧領域裡最為重要的兩個方向。如何讓機器學習方法從文字中理解人類語言內含的思想?本文中,來自 Insight AI 的 Emmanuel Ameisen 將為我們簡述絕大多數任務上我們需要遵循的思路。文章選自InsightDataScience,作者:Emmanuel Ameisen,由機器之心編譯。

文字資料無處不在

無論是成立的公司,還是致力於推出新服務,你都可以利用文字資料來驗證、改進和擴充套件產品的功能。從文字資料中提取資訊並從中學習的科學是自然語言處理(NLP)的一個活躍的研究課題。

NLP 覆蓋領域很廣,每天都會有新的令人興奮的結果。但經過與數百家公司合作,Insight 團隊發現其中有幾個重要應用出現得尤其頻繁:

  • 識別不同的使用者/客戶群(例如預測客戶流失、顧客終身價值、產品偏好)

  • 準確檢測和提取不同類別的反饋(正面和負面的評論/意見,提到的特定屬性,如衣服尺寸/合身度等)

  • 根據意圖對文字進行分類(例如尋求一般幫助,緊急問題)

儘管網上有很多 NLP 論文和教程,但我們很難找到從頭開始高效學習這些問題的指南和技巧。

本文給你的幫助

結合每年帶領數百個專案組的經驗,以及全美國最頂尖團隊的建議,我們完成了這篇文章,它將解釋如何利用機器學習方案來解決上述 NLP 問題。我們將從最簡單的方法開始,然後介紹更細緻的方案,如特徵工程、單詞向量和深度學習。

閱讀完本文後,您將會知道如何:

  • 收集、準備和檢驗資料

  • 建立簡單的模型,必要時轉化為深度學習

  • 解釋和理解模型,確保捕獲的是資訊而非噪聲

這篇文章我們將給你提供一步一步的指導;也可以作為一個提供有效標準方法的高水平概述。

這篇文章附有一個互動式 notebook,演示和應用了所有技術。你可以隨意執行程式碼,同步學習:github.com/hundredbloc…


第 1 步:收集資料

資料來源示例

每個機器學習問題都從資料開始,例如電子郵件、帖子或推文(微博)。文字資訊的常見來源包括:

  • 產品評論(來自亞馬遜,Yelp 和各種應用商店)

  • 使用者釋出的內容(推文,Facebook 上的帖子,StackOverflow 上的問題)

  • 故障排除(客戶請求,支援票據,聊天記錄)


「社交媒體中出現的災難」資料集

本文我們將使用由 CrowdFlower 提供的一個名為「社交媒體中出現的災難」的資料集,其中:

編者檢視了超過 1 萬條推文,其中包括「著火」、「隔離」和「混亂」等各種搜尋,然後看推文是否是指災難事件(排除掉用這些單詞來講笑話或評論電影等沒有發生災難的情況)。

我們的任務是檢測哪些推文關於災難性事件,排除像電影這種不相關的話題。為什麼?一個可能的應用是僅在發生緊急事件時(而不是在討論最近 Adam Sandler 的電影時)通知執法官員。

這篇文章的其它地方,我們將把關於災難的推文稱為「災難」,把其它的推文稱為「不相關事件」。


標籤

我們已經標記了資料,因此我們知道推文所屬類別。正如 Richard Socher 在下文中概述的那樣,找到並標記足夠多的資料來訓練模型通常更快、更簡單、更便宜,而非嘗試優化複雜的無監督方法。

如何解決90%的自然語言處理問題:分步指南奉上

Richard Socher 的小建議


第 2 步:清理資料

我們遵循的首要規則是:「你的模型受限於你的資料」。

資料科學家的重要技能之一就是知道下一步的工作物件是模型還是資料。一個好的方法是先檢視資料再清理資料。一個乾淨的資料集可以使模型學習有意義的特徵,而不是過度擬合無關的噪聲。

下面是一個清理資料的清單:(更多細節見程式碼 code (github.com/hundredbloc…)):

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

2. 把文字分成單獨的單詞來標記解析

3. 刪除不相關的詞,例如推文中的「@」或網址

4. 將所有字元轉換為小寫字母,使「hello」,「Hello」和「HELLO」等單詞統一

5. 考慮將拼寫錯誤和重複拼寫的單詞歸為一類(例如「cool」/「kewl」/「cooool」)

6. 考慮詞性還原(將「am」「are」「is」等詞語統一為常見形式「be」)

按這些步驟操作並檢查錯誤後,就可以使用乾淨的標籤化的資料來訓練模型啦!


第 3 步:尋找好的資料表示

機器學習模型的輸入是數值。如影象處理的模型中,用矩陣來表示各個顏色通道中每個畫素的強度。

如何解決90%的自然語言處理問題:分步指南奉上

一個笑臉可以表示為一個數字矩陣

如果我們的資料集是一系列的句子,為了使演算法可以從資料中提取特徵,我們需要表示為可以被演算法識別的形式,如表示為一系列數字。


One-hot encoding(詞袋模型)

表示文字的一種常見方法是將每個字元單獨編碼為一個數字(例如 ASCII)。如果我們直接把這種簡單的形式用於分類器,那隻能基於我們的資料從頭開始學習單詞的結構,這對於大多數資料集是不可實現的。因此,我們需要一個更高階的方法。

例如,我們可以為資料集中的所有單詞建立一個詞彙表,每個單詞對應一個不同的數字(索引)。那句子就可以表示成長度為詞彙表中不同單詞的一個列表。在列表的每個索引處,標記該單詞在句子中出現的次數。這就是詞袋模型(Bag of Words),這種表示完全忽略了句子中單詞的順序。如下所示。

如何解決90%的自然語言處理問題:分步指南奉上

將句子表示為詞袋。左邊為句子,右邊為對應的表示,向量中的每個數字(索引)代表一個特定的單詞。


視覺化詞嵌入

在「社交媒體中出現的災難」一例中,大約有 2 萬字的詞彙,這代表每個句子都將被表示為長度為 2 萬的向量。向量中有很多 0,因為每個句子只包含詞彙表中非常小的一個子集。

為了瞭解詞嵌入是否捕獲到了與問題相關的資訊(如推文是否說的是災難),有一個很好的辦法,就是將它們視覺化並看這些類的分離程度。由於詞彙表很大,在 20,000 個維度上視覺化資料是不可能的,因此需要主成分分析(PCA)這樣的方法將資料分到兩個維度。如下圖所示。

如何解決90%的自然語言處理問題:分步指南奉上

將嵌入的詞袋視覺化

看起來很難分為兩類,也不好去降低維度,這是嵌入的一個特點。為了瞭解詞袋模型特徵是否有用,我們可以基於它們訓練一個分類器。


第 4 步:分類器

遇到一個問題時,通常從尋找解決問題的工具入手。當我們要對資料進行分類時,出於通用性和可解釋性的考慮,通常使用 Logistic 迴歸(Logistic Regression)。訓練非常簡單,結果也可解釋,因為易於從模型提取出最重要的引數。

我們將資料分成一個用於擬合模型的訓練集和一個用於分析對不可見資料擬合程度的測試集。訓練結束後,準確率為 75.4%。還看得過去!最頻繁的一類(「不相關事件」)僅為 57%。但即使只有 75% 的準確率也足以滿足我們的需要了,一定要在理解的基礎上建模。


第 5 步:檢驗

混淆矩陣(Confusion Matrix)

首先要知道我們模型的錯誤型別,以及最不期望的是哪種錯誤。在我們的例子中,誤報指將不相關的推文分類為災難,漏報指將關於災難的推文歸為不相關事件。如果要優先處理每個可能的事件,那我們想降低漏報的情況。如果我們優先考慮資源有限的問題,那我們會優先降低誤報的情況,從而減少誤報的提醒。我們可以用混淆矩陣來視覺化這些資訊,混淆矩陣將我們模型預測的結果與真實情況進行比較。理想情況下(我們的預測結果與真實情況完全相符),矩陣為從左上到右下的一個對角矩陣。

如何解決90%的自然語言處理問題:分步指南奉上

混淆矩陣(綠色比例大,藍色比例小)

我們的分類器的漏報情況(相對)高於誤報情況。也就是說,這個模型很可能錯誤地將災難歸為不相關事件。如果誤報情況下執法的成本很高,那我們更傾向於使用這個分類器。


解釋模型

為了驗證模型並解釋模型的預測,我們需要看哪些單詞在預測中起主要作用。如果資料有偏差,分類器會對樣本資料作出準確的預測,但在實際應用時模型預測的效果並不理想。下圖中我們給出了關於災難和不相關事件的重要詞彙。我們可以提取並比較模型中的預測係數,所以用詞袋模型和 Logistic 迴歸來尋找重要詞彙非常簡單。

如何解決90%的自然語言處理問題:分步指南奉上

詞袋:重要詞彙

我們的分類器正確地找到了一些模式(廣島,大屠殺),但顯然這是無意義資料的過度擬合(heyoo, x1392)。現在我們的詞袋模型正在處理一個龐大的詞彙表,所有詞彙對它來說都是一樣的。但一些詞彙出現地非常頻繁,而且只會對我們的預測加入噪聲。接下來,我們試著用一個方法來表示詞彙出現的頻率,看我們能否從資料中獲得更多的訊號。


第 6 步:統計詞彙

TF-IDF

為了使模型更關注有意義的單詞,我們可以使用 TF-IDF(詞頻-逆文件頻率)對我們的詞袋模型進行評估。TF-IDF 通過對資料集中詞彙出現的頻率來加權,並減小高頻但只是增加噪音的單詞的權重。這是我們新嵌入的 PCA 預測。

如何解決90%的自然語言處理問題:分步指南奉上

將 TF-IDF 嵌入視覺化

由上圖我們看到,兩種顏色的資料差別更加明顯。這使分類器分組更加容易。讓我們來看一下這樣結果是否會更好。訓練新嵌入的 Logistic 迴歸,我們得到了 76.2%的準確率。

只是稍稍地進行了改進。那現在我們的模型可以選擇更重要的單詞了嗎?如果模型預測時有效地繞過了「陷阱」,得到了更好的結果,那就可以說,這個模型得到了優化。

如何解決90%的自然語言處理問題:分步指南奉上

TF-IDF:重要詞彙

挑出來的單詞似乎更加相關了!儘管我們測試集的指標稍有增加,但模型使用的詞彙更加關鍵了,因此我們說「整個系統執行時與客戶的互動更加舒適有效」。


第 7 步:利用語義

Word2Vec

我們最新的模型可以挑出高訊號的單詞。但很可能我們運作模型時會遇到訓練集中沒有單詞。因此,即使在訓練中遇到非常相似的單詞,之前的模型也不會準確地對這些推文進行分類。

為了解決這個問題,我們需要捕獲單詞的含義,也就是說,需要理解「good」和「positive」更接近而不是「apricot」或「continent」。用來捕獲單詞含義的工具叫 Word2Vec。


使用預訓練的單詞

Word2Vec 是尋找單詞連續 embedding 的技術。通過閱讀大量的文字學習,並記憶哪些單詞傾向於相似的語境。訓練足夠多的資料後,詞彙表中的每個單詞會生成一個 300 維的向量,由意思相近的單詞構成。

論文《Efficient Estimation of Word Representations in Vector Space》的作者開源了一個模型,對一個足夠大的可用的語料庫進行預訓練,將其中的一些語義納入我們的模型中。預訓練的向量可以在這篇文章相關的資源庫中找到:https://github.com/hundredblocks/concrete_NLP_tutorial。


句子的表示

快速得到分類器的 sentence embedding 的一個方法是平均對句子中的所有單詞的 Word2Vec 評估。這和之前詞袋模型是一個意思,但這次我們保留一些語言資訊,僅忽略句子的語法。

如何解決90%的自然語言處理問題:分步指南奉上


以下是之前技術的新嵌入的視覺化:

如何解決90%的自然語言處理問題:分步指南奉上

視覺化 Word2Vec 嵌入

這兩種顏色的資料更明顯地分離了,我們新的嵌入可以使分類器找到兩類之前的分離。經過第三次訓練同一個模型後(Logistic 迴歸),我們得到了 77.7%的準確率,這是目前最好的結果!可以檢驗我們的模型了。


複雜性/可解釋性的權衡

我們的 embedding 沒有向之前的模型那樣每個單詞表示為一維的向量,所以很驗證看出哪些單詞和我們的向量最相關,。雖然我們仍可以使用 Logistic 迴歸的係數,但它們和我們 embedding 的 300 個維度有關,而不再是單詞的索引。

它的準確率這麼低,拋掉所有的可解釋性似乎是一個粗糙的權衡。但對於更復雜的模型來說,我們可以利用 LIME 之類的黑盒直譯器(black box explainers)來深入瞭解分類器的工作原理。


LIME

可以通過開源軟體包在 Github 上找到 LIME:https://github.com/marcotcr/lime

黑盒直譯器允許使用者通過擾亂輸入並觀察預測的變化來解釋一個特定例子的任何分類器的決定。

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

如何解決90%的自然語言處理問題:分步指南奉上

挑選正確的災難詞彙並歸類為「相關」。

如何解決90%的自然語言處理問題:分步指南奉上


這裡,這個詞對分類器的造成的影響似乎不太明顯。

但是,我們沒有時間去探索資料集中的數千個示例。我們要做的是在測試例子的代表樣本上執行 LIME,看哪些詞彙做的貢獻大。使用這種方式,我們可以像之前的模型一樣對重要單詞進行評估,並驗證模型的預測結果。

如何解決90%的自然語言處理問題:分步指南奉上

Word2Vec:重要單詞

模型提取的高度相關的詞意味它可以做出更加可解釋的決定。這些看起來像是之前模型中最相關的詞彙,因此我們更願意將其加入到我們的模型中。


第 8 步:使用端到端(end-to-end)方法

我們已經介紹了生成簡潔句嵌入快速有效的方法。但是由於忽略了單詞的順序,我們跳過了句子所有的語法資訊。如果這些方法提供的結果不充分,那我們可以使用更復雜的模型,輸入整個句子並預測標籤,而不需要中間表示。一個常見的方法是使用 Word2Vec 或更類似的方法(如 GloVe 或 CoVe)將句子看作一個單詞向量的序列。這就是我們下文中要做的。

如何解決90%的自然語言處理問題:分步指南奉上

高效的端到端結構

用於句子分類的卷積神經網路訓練非常迅速,作為入門級深度學習體系效果非常理想。雖然卷積神經網路(CNN)主要因為在影象處理的使用而廣為人知,但它們在處理文字相關任務時得到的結果也非常好,而且通常比大多數複雜的 NLP 方法(如 LSTMs 和 Encoder/Decoder 結構)訓練地更快。這個模型考慮了單詞的順序,並學習了哪些單詞序列可以預測目標類等有價值的資訊,可以區別「Alex eats plants」和「Plants eat Alex」。

訓練這個模型不用比之前的模型做更多的工作,並且效果更好,準確率達到了 79.5%!詳見程式碼:github.com/hundredbloc…

與上述模型一樣,下一步我們要使用此方法來探索和解釋預測,以驗證它是否是給使用者提供的最好的模型。到現在,你應該對這樣的問題輕車熟路了。


結語

下面對我們成功使用的方法進行簡要回顧:

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

  • 解釋其預測

  • 瞭解其錯誤型別

  • 根據以上知識來判斷下一步的工作——處理資料還是尋找更復雜的模型

這些方法只用於特定的例子——使用適當的模型來理解和利用短文字(推文),但這種思想適用於各種問題。希望這篇文章對你有所幫助,也歡迎大家提出意見和問題!


相關文章