乾貨教程|自然語言處理入門:手把手教你解決90%的NLP問題

碼字不易,歡迎給個贊!

歡迎交流與轉載,文章會同步發布在公眾號:機器學習演算法全棧工程師(Jeemy110)

文章來自:blog.insightdatascience.com

作者:Emmanuel Ameisen

譯者:孟廉

前言

無論您是一個成熟的公司,還是致力於推出一個新服務,您都可以利用文本數據來驗證、改進和擴展您的產品的功能。從文本數據中提取有意義的信息並對其進行學習是自然語言處理(NLP)的一個研究活躍的課題。

NLP領域每天都會產生新的令人興奮的結果,在與數百家公司合作之後,Insight團隊發現一些比較關鍵的實際應用比其他應用出現得更為頻繁,具體來說有以下幾種:

  1. 識別不同的用戶/客戶群體(如預測流動率、壽命值、產品偏好)

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

  3. 根據意圖對文本進行分類(例如,請求基本幫助,緊急問題)

在每年領導數百個項目的經驗,並從美國各地的頂級團隊那裡獲得建議之後,我們撰寫了這篇文章,解釋了如何構建機器學習解決方案來解決上面提到的問題。我們將從最簡單的方法開始,然後轉向更細緻的解決方案,比如特徵工程、單詞向量和深度學習。

讀完這篇文章,你會知道如何:

  1. 收集、準備和檢查數據;
  2. 建立簡單的模型,並在必要時向深度學習過渡;
  3. 解釋和理解你的模型,以確保你實際上是在獲取信息而不是噪音。

我們把這篇文章作為一個循序漸進的指南,它也可以作為高度有效的標準方法的高級概述,這篇文章附有一個互動式 notebook,你可以隨意運行代碼同步學習:

hundredblocks/concrete_NLP_tutorial?

github.com圖標

1. 收集你的數據

示例數據來源

每一個機器學習問題都是從數據開始的,比如電子郵件、帖子或推文(微博)。文本信息的來源包括:

  1. 產品評論(在亞馬遜,Yelp和各種應用商店)
  2. 用戶發布的內容(Tweets,Facebook帖子,StackOverflow問題)
  3. 其他類信息(客戶請求、支持票據、聊天記錄)

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

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

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

2. 清洗數據

我們遵循的第一條規則是:「你的模型會受你數據的影響。」

數據科學家的關鍵技能之一是知道下一步的工作對象應該是模型還是數據。對於數據清洗,一個好的經驗法則是先查看數據然後再進行清理。一個乾淨的數據集將使得一個模型學到有意義的特性,而不是過度擬合無關的噪音。

以下是用來清理你的數據的清單:

  1. 刪除所有不相關的字元,例如任何非字母數字字元;
  2. 把你的文章分成一個個單獨的單詞;
  3. 刪除不相關的單詞,比如「@」twitter或網址;
  4. 將所有字元轉換為小寫,以處理諸如「hello」、「Hello」和「HELLO」等單詞;
  5. 考慮將拼錯的單詞或拼寫單片語合成一類(如:「cool」/「kewl」/「cooool」);
  6. 考慮詞性還原(將「am」「are」「is」等詞語統一為常見形式「be」)。

在遵循這些步驟並檢查額外的錯誤之後,我們就可以開始使用乾淨的、標記的數據來訓練模型!

3. 尋找好的數據表示

機器學習模型以數值作為輸入。例如,在圖像上工作的模型,可以採用表示每個顏色通道中每個像素強度的矩陣。

一個以數字矩陣表示的笑臉

我們的數據集是一個句子的列表,所以為了讓我們的演算法從數據中提取模式,我們首先需要找到一種方法來使得以我們的演算法能夠理解的方式來表示它,也就是一個數字列表。

One-hot encoding (詞袋模型)

表示計算機文本的一種自然方法是將每個字元單獨編碼為一個數字(例如ASCII編碼)。如果我們要將這個簡單的表示輸入到分類器中,那麼它必須只能根據我們的數據來學習單詞的結構,這對於大多數數據集來說是不可能的,我們需要使用更高級的方法。

例如,我們可以在我們的數據集中建立一個所有的單詞的辭彙表,並將一個唯一的索引與辭彙表中的每個單詞聯繫起來。每個句子被表示為一個列表,只要我們的辭彙表中有不同單詞的數量。在這個列表中的每個索引中,我們標記出在我們的句子中出現了多少次給定的單詞。這被稱為詞袋模型,因為它是一種完全無視我們句子中詞語順序的表現形式,如下圖所示:

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

可視化詞嵌入

在「社交媒體中出現的災難」例子中,我們的辭彙量大約有2萬個單詞,這意味著每一個句子都將被表示成一個長度為2萬的向量。這個向量幾乎包含了0,因為每個句子只包含了我們辭彙量的一小部分。

為了查看我們的嵌入是否捕獲了與我們的問題相關的信息(例如,tweet是否與災難有關),可視化它們並查看這些類的分離程度,這是一個好主意。由於辭彙表通常是非常大的,並且在20,000個維度中可視化數據是不可能的,因此需要主成分分析(PCA)這樣的技術將有助於將數據壓縮到兩個維度,如下圖所示:

將嵌入的詞袋可視化

這兩個類看起來並沒有很好地分離,這可能是我們嵌入的一個特性,或者僅僅是我們的維度縮減。為了了解這些詞的特點是否有任何用途,我們可以根據它們來訓練一個分類器。

4. 分類

面對一個問題時,一般好的做法是從最簡單的工具開始由淺入深地解決問題。當提到數據分類時,人們最喜歡方法是的 Logistic 回歸(Logistic Regression),這是一種非常簡單的訓練方法,結果是可以解釋的,因為你可以很容易地從模型中提取最重要的參數。

我們將數據分解為一個訓練集,用於擬合我們的模型和一個測試集,以查看它對不可見的數據的概括程度。經過訓練,我們的準確率達到了75.4%,不至於太難看。然而,即使75%的精度滿足了我們的需求,我們也不應該在不理解模型的情況下發布模型。

4. 檢查

混淆矩陣(Confusion Matrix)

第一步是了解我們模型所出的錯誤類型,以及哪些錯誤是最不可取的。在我們的例子中, false positive將一個無關的推文歸類為災難,而 false negtive則將災難分類為不相關的tweet。如果首要任務是對每一個潛在事件優先處理,我們就想降低我們的false negtive結果。如果我們優先考慮資源受限的問題,我們可能會優先考慮降低false positive率以減少誤報的提醒。一個很好的可視化這個信息的方法是使用一個混淆矩陣,它比較了我們的模型和真實的標籤的預測。理想情況下,矩陣將是一條從左上到右下的對角線(即我們的預測完全符合事實)。

我們的分類器創造了更多的false negtive,而不是false positive(比例)。換句話說,我們的模型最常見的錯誤是錯誤地將災難分類為無關緊要的。如果誤報是執法的高成本,我們更傾向於使用這個分類器。

解釋我們的模型

為了驗證我們的模型並解釋它的預測,重要的是看一下它用哪些單詞在預測中起主要作用。如果我們的數據有偏差,我們的分類器會在樣本數據中做出準確的預測,但是模型在實際應用效果並不理想。在這裡,我們給出了災難和不相關事件的重要辭彙。用詞袋模型和Logistic 回歸來描繪單詞的重要性是很簡單的,因為我們可以提取和排列模型用於預測的係數。

我們的分類器正確地選擇了一些模式(廣島,大屠殺),但顯然似乎是過度擬合一些無意義的術語(heyoo, x1392)。現在,我們的詞袋模型是處理大量不同單詞的辭彙,並對所有單詞一視同仁。然而,有些詞是非常頻繁的,而且只會對我們的預測造成干擾。接下來,我們將嘗試著用一個方法來表示辭彙出現的頻率,看我們能否從數據中獲得更多的信號。

6. 解釋

TF-IDF

為了幫助我們的模型更多地關注有意義的單詞,我們可以在我們的單詞模型包上使用TF-IDF評分(詞頻-逆文檔頻率)。TF-IDF 通過對數據集中辭彙出現的頻率來加權,並減小高頻但只是增加噪音的單詞的權重,這是我們新嵌入的 PCA 預測。

TF-IDF 嵌入可視化

我們可以看到,這兩種顏色之間有更明顯的區別,這將使我們的分類器更容易區分兩個組。讓我們看看這會不會帶來更好的性能。在我們新嵌入的邏輯回歸,我們得到了76.2%的精確度。

一個非常輕微的改善,我們的模型是否可以選擇更重要的辭彙?如果我們在防止模型從「欺騙」中得到更好的結果,那麼我們就可以說這個模型得到了優化。

TF-IDF:重要辭彙

它挑選的單詞看起來更加相關了!雖然我們在測試集上的指標只稍微增加了一點,但是我們對我們的模型使用的辭彙更加關鍵,因此在將它部署到與客戶交互的系統中會更舒適有效。

7. 利用語意信息

Word2Vec

我們的最新型號成功地挑出了高信號詞。然而,很有可能的是,如果我們部署這個模型,我們將會遇到以前在我們的訓練中沒有看到的單詞。之前的模型將無法準確地對這些推文進行分類,即使在訓練過程中看到了非常相似的單詞。

為了解決這個問題,我們需要抓住詞語的語義含義,這意味著我們需要理解像「good」和「positive」更接近而不是「apricot」和「continent」。我們用來幫助我們捕捉單詞含義的工具叫做Word2Vec。

使用預訓練的單詞

Word2Vec 是尋找單詞連續 embedding 的技術。它可以從閱讀大量的文本中學習,並記住在類似的語境中出現的單詞。在對足夠的數據進行訓練之後,它會在辭彙表中為每個單詞生成一個300維的向量,而單詞之間的意思相近。

句子層面表示

一個快速得到分類器的 sentence embedding 的方法是平均對句子中的所有單詞的 Word2Vec 評估。這是一個像以前一樣的詞袋模型,但是這次我們只會忽略句子的語法,同時保留一些語義信息。

下面是我們使用以前的技術實現的新嵌入的可視化:

可視化 Word2Vec 嵌入

這兩組顏色看起來更加分離,我們的新嵌入應該幫助分類器找到兩個類之間的分離。在訓練了相同的模型第三次(Logistic 回歸)後,我們得到了77.7%的準確率,這是我們最好的結果!是時候檢查我們的模型了。

複雜性/ 可解釋性權衡

由於我們的embedding不是像之前的模型那樣以每個單詞表示為一個維度,因此很難看出哪些單詞與我們的分類最相關。雖然我們仍然可以使用Logistic回歸的係數,但它們與我們的embedding 的300個維度有關,而不是單詞的索引。

對於如此低的精確度,失去所有的解釋能力似乎是一種苛刻的取捨。但是,對於更複雜的模型,我們可以利用像LIME這樣的黑盒解釋器來了解我們的分類器是如何工作的。

8. 利用端到端(end-to-end)的方法

我們已經介紹了快速和有效的方法來生成緊湊的句子嵌入。然而省略了單詞的順序,我們跳過了句子所有的句法信息。如果這些方法沒有提供足夠的結果,我們可以使用更複雜的模型,將整個句子作為輸入並預測標籤,而不需要構建中間表示。一種常見的方法是使用Word2Vec或更類似的方法,如GloVe或CoVe,將句子看作一個單詞向量的序列,這就是我們接下來要做的。

高效的端到端結構

論文《Convolutional Neural Networks for Sentence Classification》中的模型訓練分類模型非常快,並且它是作為入門級的深度學習體系效果非常理想。雖然卷積神經網路(CNN)主要以其在圖像數據上的性能而著稱,但它們在與文本相關的任務上同樣也展示了出色的結果,而且通常比大多數複雜的NLP方法(例如LSTMs和Encoder/Decoder結構)訓練更快。這個模型保存了單詞的順序,並學習了有價值的信息,並學習了哪些單詞序列可以預測目標類等有價值的信息,可以區別「Alex eats plants」和「Plants eat Alex」。

訓練這個模型不需要比以前的方法做更多的工作,並且效果更好,獲得79.5%的準確性!見代碼:

https://github.com/hundredblocks/concrete_NLP_tutorial/blob/master/NLP_notebook.ipynb。與上面的模型一樣,下一步應該使用我們描述的方法來探索和解釋預測,以驗證它確實是給用戶提供的最佳模型。到現在為止,你應該對解決這類問題很熟練了。

最後的話

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

  1. 從一個簡單的模型開始;
  2. 解釋其預測;
  3. 理解其錯誤類型;
  4. 使用這些知識來判斷下一步的工作,無論是正在處理您的數據,還是一個更複雜的模型。

這些方法只應用於一個特定的例子,使用的模型是針對理解和利用短文本(如tweet)而進行的,但是這些想法廣泛適用於各種問題。希望這會對你有所幫助,我們很樂意聽到你的評論和問題!

碼字不易,歡迎給個贊!

歡迎交流與轉載,文章會同步發布在公眾號:機器學習演算法全棧工程師(Jeemy110)

推薦閱讀:

SQLnet 代碼閱讀筆記
TextGAN 代碼閱讀筆記
為何讀不懂你的那個TA
Joint Extraction of Entities and RelationsBased on a Novel Tagging Scheme

TAG:自然語言處理 | 深度學習DeepLearning | 人工智慧 |