現代情感分析方法

Ree Ray發表於2017-06-28

情感分析(Sentiment analysis)是自然語言處理(NLP)方法中常見的應用,尤其是以提煉文字情緒內容為目的的分類。利用情感分析這樣的方法,可以通過情感評分對定性資料進行定量分析。雖然情感充滿了主觀性,但情感定量分析已經有許多實用功能,例如企業藉此瞭解使用者對產品的反映,或者判別線上評論中的仇恨言論。

情感分析最簡單的形式就是藉助包含積極和消極詞的字典。每個詞在情感上都有分值,通常 +1 代表積極情緒,-1 代表消極。接著,我們簡單累加句子中所有詞的情感分值來計算最終的總分。顯而易見,這樣的做法存在許多缺陷,最重要的就是忽略了語境(context)和鄰近的詞。例如一個簡單的短語“not good”最終的情感得分是 0,因為“not”是 -1,“good”是 +1。正常人會將這個短語歸類為消極情緒,儘管有“good”的出現。

另一個常見的做法是以文字進行“詞袋(bag of words)”建模。我們把每個文字視為 1 到 N 的向量,N 是所有詞彙(vocabulary)的大小。每一列是一個詞,對應的值是這個詞出現的次數。比如說短語“bag of bag of words”可以編碼為 [2, 2, 1]。這個值可以作為諸如邏輯迴歸(logistic regression)、支援向量機(SVM)的機器學習演算法的輸入,以此來進行分類。這樣可以對未知的(unseen)資料進行情感預測。注意這需要已知情感的資料通過監督式學習的方式(supervised fashion)來訓練。雖然和前一個方法相比有了明顯的進步,但依然忽略了語境,而且資料的大小會隨著詞彙的大小增加。

Word2Vec 和 Doc2Vec

近幾年,Google 開發了名為 Word2Vec 新方法,既能獲取詞的語境,同時又減少了資料大小。Word2Vec 實際上有兩種不一樣的方法:CBOW(Continuous Bag of Words,連續詞袋)和 Skip-gram。對於 CBOW,目標是在給定鄰近詞的情況下預測單獨的單詞。Skip-gram 則相反:我們希望給定一個單獨的詞(見圖 1)來預測某個範圍的詞。兩個方法都使用人工神經網路(Artificial Neural Networks)來作為它們的分類演算法。首先,詞彙表中的每個單詞都是隨機的 N 維向量。在訓練過程中,演算法會利用 CBOW 或者 Skip-gram 來學習每個詞的最優向量。sentiment_01_large圖 1:CBOW 以及 Skip-Gram 結構圖,選自《Efficient Estimation of Word Representations in Vector Space》。W(t) 代表當前的單詞,而w(t-2), w(t-1) 等則是鄰近的單詞。

這些詞向量現在可以考慮到上下文的語境了。這可以看作是利用基本的代數式來挖掘詞的關係(例如:“king” – “man” + “woman” = “queen”)。這些詞向量可以作為分類演算法的輸入來預測情感,有別於詞袋模型的方法。這樣的優勢在於我們可以聯絡詞的語境,並且我們的特徵空間(feature space)的維度非常低(通常約為 300,相對於約為 100000 的詞彙)。在神經網路提取出這些特徵之後,我們還必須手動建立一小部分特徵。由於文字長度不一,將以全體詞向量的均值作為分類演算法的輸入來歸類整個文件。

然而,即使使用了上述對詞向量取均值的方法,我們仍然忽略了詞序。Quoc Le 和 Tomas Mikolov 提出了 Doc2Vec 的方法對長度不一的文字進行描述。這個方法除了在原有基礎上新增 paragraph / document 向量以外,基本和 Word2Vec 一致,也存在兩種方法:DM(Distributed Memory,分散式記憶體)和分散式詞袋(DBOW)。DM 試圖在給定前面部分的詞和 paragraph 向量來預測後面單獨的單詞。即使文字中的語境在變化,但 paragraph 向量不會變化,並且能儲存詞序資訊。DBOW 則利用paragraph 來預測段落中一組隨機的詞(見圖 2)。

sentiment_02_large

圖 2: Doc2Vec 方法結構圖,選自《Distributed Representations of Sentences and Documents》。

一旦經過訓練,paragraph 向量就可以作為情感分類器的輸入而不需要所有單詞。這是目前對 IMDB 電影評論資料集進行情感分類最先進的方法,錯誤率只有 7.42%。當然,如果這個方法不實用,說這些都沒有意義。幸運的是,一個 Python 第三方庫 gensim 提供了 Word2Vec 和 Doc2Vec 的優化版本。

基於 Python 的 Word2Vec 舉例

在本節我們將會展示怎麼在情感分類任務中使用詞向量。gensim 這個庫是 Anaconda 發行版中的標配,你同樣可以利用 pip 來安裝。利用它你可以在自己的語料庫(一個文件資料集)中訓練詞向量或者匯入 C text 或二進位制格式的已經訓練好的向量。

我發現讀取谷歌已經訓練好的詞向量尤其管用,這些向量來自谷歌新聞(Google News),由超過千億級別的詞訓練而成,“已經訓練過的詞和短語向量”可以在這裡找到。注意未壓縮的檔案有 3.5 G。通過 Google 詞向量我們能夠發現詞與詞之間有趣的關聯:

有趣的是它可以發現語法關係,例如識別最高階(superlatives)和動詞詞幹(stems):

“biggest” – “big” + “small” = “smallest”

“ate” – “eat” + “speak” = “spoke”

由以上例子可以清楚認識到 Word2Vec 能夠學習詞與詞之間的有意義的關係。這也就是為什麼它對於許多 NLP 任務有如此大的威力,包括在本文中的情感分析。在我們用它解決起情感分析問題以前,讓我們先測試一下 Word2Vec 對詞分類(separate)和聚類(cluster)的本事。我們會用到三個示例詞集:食物類(food)、運動類(sports)和天氣類(weather),選自一個非常棒的網站 Enchanted Learning。因為這些向量有 300 個維度,為了在 2D 平面上視覺化,我們會用到 Scikit-Learn’s 中叫作“t-SNE”的降維演算法操作

首先必須像下面這樣取得詞向量:

我們接著使用 TSNEmatplotlib 視覺化聚類,程式碼如下:

結果如下:

sentiment_03_large

圖 3:食物類單詞(藍色),運動類單詞(紅色)和天氣類單詞(綠色)T-SNE 叢集效果圖。

我們可以從上面的例子看到,Word2Vec 不僅能有效分類不相關的單詞,同樣也能聚類類似的詞。

推特 Emoji 情感分析

現在我們進入下一個例程,利用符號表情作為搜尋詞的推特情感分析。我們把這些符號表情作為我們資料的“模糊(fuzzy)”標籤;微笑表情(:-))與積極情緒對應,而皺眉表情(:-()則對應消極情緒。在大約 400,000 條推特資料中,積極和消極的各佔一半(even split)。我們對積極和消極情緒的推特進行了隨機取樣,並按80 / 20 的比例分為了訓練集/ 測試集。我們接著在 Word2Vec 模型上訓練推特。為了避免資料洩露(data leakage),在訓練資料集分類完成以前我們都不會在 Word2Vec 上訓練。為了結構化分類器的輸入,我們對所有推特詞向量取均值。我們會用到 Scikit-Learn 這個第三方庫做大量的機器學習。

我們首先匯入我們的資料並訓練 Word2Vec 模型

下面我們必須對輸入文字建立詞向量,為了平均推特中的所有詞向量,將用到如下的函式:

對我們的資料集進行縮放是標準化處理的一部分。通過均值為零的高斯分佈,意味著大於均值則為積極,小於則為消極。許多機器學習模型要求使用縮放過的資料集來獲得更好的處理效果,尤其是多特徵(例如文字分類)。

最終我們必須建立測試資料向量並進行比例縮放來評估。

下面我們想通過計算測試資料的預測精度來驗證我們的分類器,同時測試它們的 ROC 曲線(Receiver Operating Characteristic,受試者操作特徵曲線)。當模型引數調節時,ROC 曲線會測試分類器的真陽性(true-positive)以及假陽性(false-positive)。本例中,我們通過調節邊界閾值概率(cut-off threshold probability)將某條推特分類為積極或消極情緒。通常,更希望得到最大化的真陽性和最小化的假陽性,也就是 ROC 曲線下方最大的區域(AUC)。通過這裡更多地瞭解 ROC 曲線。

開始訓練我們的分類器,本例對邏輯迴歸(Logistic Regression)使用隨機梯度下降(Stochastic Gradient Descent)。

我們利用 matplotlib 和 Scikit-Learn 的 metric 包中的 roc_curve 建立 ROC 曲線來評估。

曲線結果如下:

sentiment_04_large

圖 4:邏輯分類器對推特訓練資料的 ROC 曲線

沒有建立任何特徵以及最小化的文字預處理,利用 Scikit-Learn 提供的簡單線性模型我們已經實現了 73% 的測試準確率。有趣的是,移除了標點符號實際上反而降低了準確率,說明當“?”或“!”出現時,Word2Vec 能夠找到有趣的特徵。將這些標點視為獨立的單詞,訓練更長的時間,做更多的預處理,調節 Word2Vec 和分類器中的引數這些方法都有助於準確率的提升。我已經發現配合使用人工神經網路(ANN)能夠提高大概 5% 的準確率。因為 Scikit-Learn 沒有提供 ANN 分類器的實現工具,所以我自己寫了一個:

最終準確率為 77%。不論什麼機器學習任務,選對模型的藝術性大於科學性。如果你想用我寫的庫你可以在找到。友情提示,它看起來比較亂並且沒有定期維護!如果你想貢獻程式碼歡迎 fork 我的程式碼倉。它非常需要被寵幸(TLC)。

基於 Doc2Vec 的電影評論分析

在推特的例子中,使用詞向量的均值效果良好。這是因為推特通常是幾十個詞的長度,即使取均值也能保留相關的特徵。然而,一旦我們上升到段落的規模,忽略詞序和上下文資訊將面臨丟失大量特徵的風險。這樣的情況下更適合使用 Doc2Vec 建立輸入特徵。我們將使用 IMDB 電影評論資料集 作為示例來測試 Word2Vec 在情感分析中的有效性。資料集中包含了 25,000 條積極評論,25,000 條消極評論和 50,000 條未標記的電影評論。我們首先利用 Doc2Vec 對未標記評論進行訓練。除了同時使用 DM 和 DBOW 向量作為輸入以外,方法和上一節 Word2Vec 例子相同。

這麼一來建立了 LabeledSentence 型別物件:

下面我們例項化兩個 Doc2Vec 模型,DM 和 DBOW。gensim 文件建議多次訓練資料,並且在每一步(pass)調節學習率(learning rate)或者用隨機順序輸入文字。接著我們收集了通過模型訓練後的電影評論向量。

現在我們準備對我們的評論向量訓練一個分類器。我們再次使用 sklearn 的 SGDClassifier

這個模型的測試準確率達到了 0.86。我們也構建瞭如下的分類器 ROC 曲線:

sentiment_05_large

圖 5:基於 IMDB 電影評論訓練資料的邏輯分類器(logistic classifier)的 ROC 曲線

原始論文 強調了用有 50 個結點的神經網路加上一個簡單的邏輯迴歸分類器,效果會有提高:

有趣的是,我們在這兒並沒有看到什麼提高。測試準確率是 0.85,我們也沒能達到他們所說的 7.42% 的測試錯誤率。原因有很多:我們在每一步(epochs)對於訓練/測試資料沒有訓練足夠,他們實現 Doc2Vec 和 ANN 的方式不同,他們的超引數不同等等。因為論文中並沒有談及細節,所以難以確知真正原因。不管怎樣,在進行了零星預處理以及沒有構造和選取特徵的情況下,我們還是得到了 86% 的準確率。並不需要花哨的卷積(convolutions)和樹庫(treebanks)!

結論

我希望已經你不僅見識了 Word2Vec 和 Doc2Vec 的強大,而且能夠通過標準工具諸如 Python 和 gensim 來應用它們。只需要非常簡單的演算法我們即可得到豐富的詞和段落向量,足以在所有 NLP 應用中使用。另外更棒的是 Google 釋出了基於超大規模資料集預訓練(pre-train)的詞向量。如果你想在大規模資料集中訓練自己的詞向量,可以利用 Apache Spark’s MLlib 的 Word2Vec 來實現。Happy NLP’ing!

擴充套件閱讀

如果你喜歡這篇文章並且不想錯過其它同類文章,在部落格主頁點選 Subscribe 的按鈕吧!

打賞支援我翻譯更多好文章,謝謝!

打賞譯者

打賞支援我翻譯更多好文章,謝謝!

任選一種支付方式

現代情感分析方法 現代情感分析方法

相關文章