1. 程式人生 > >fasttext ---強大的文字分類

fasttext ---強大的文字分類

最近接觸到自然語言處理,需要對網上新聞進行文字分類,所以入坑fasttext。 之前用過CNN網路寫過文字分類,直到本渣接觸到了fasttext,才發現,人生苦短,我要快!

這篇文章是轉載自 https://blog.csdn.net/weixin_36604953/article/details/78324834 這個江戶川大神@夏洛克江戶川,文章通俗易懂 

文字分類需要CNN?No!fastText完美解決你的需求(後篇)

想必通過前一篇的介紹,各位小主已經對word2vec以及CBOW和Skip-gram有了比較清晰的瞭解。在這一篇中,小編帶大家走進業內最新潮的文字分類演算法,也就是fastText分類器。fastText與word2vec的提出者之所以會想到用fastText取代CNN(卷積神經網路)等深度學習模型,目的是為了在大資料情況下提高運算速度。 
其實,文字的學習與影象的學習是不同的。學習不同,一般情況下,文字學習並不需要過多隱藏層、過複雜的神經網路,為什麼這麼說呢?打個比方,有這樣一句話:“柯南是個聰明的帥哥”,如果讓你去學習理解這句話,聽上二三十次次與聽上兩三次相比,對於這句話的理解可能也沒有什麼提升,就模型而言,不需要過複雜的神經網路就可以很好的對這句話進行學習,然而影象不同,如果讓你臨摹一個大師的化作,你第一次臨摹可能是個四不像,但第一萬次臨摹,可能就會以假亂真了。所以,用簡單的網路對自然語言進行學習,可以快速、高質量的得到結果。正因如此,才有了fastText演算法。 
言歸正傳,我們開始fastText演算法的深入瞭解,這篇文章主要從三個方面來介紹演算法:模型架構、分層softmax、n-gram特徵。在演算法原理介紹完畢後,同上一篇文章一樣,會帶領各位小主實現fastText演算法的應用,迫不及待了吧?

預備知識

為了更好的理解fastText,我們先來了解一些預備知識。第一個是BoW模型,也叫做詞袋模型。BoW模型(Bag of words)應用於自然語言處理、資訊檢索和影象分類等方面。它忽略掉文字的語法和語序等要素(舉個例子,Bow模型認為“我愛你”和“你愛我”是相同的,如果我們的世界是一個BoW模型該有多好,再也不會出現對女神單相思的情況了),將其僅僅看作是若干詞彙的集合。BoW 使用一組無序的單詞(word)來表達一段文字或一個文件,並且文件中每個單詞的出現都是獨立的。

例如:首先給出兩個簡單的文字文件如下: 
John likes to watch movies. Mary likes too. 


John also likes to watch football games.

基於上述兩個文件中出現的單詞,構建如下一個詞典 (dictionary): 

{“John”: 1, “likes”: 2,”to”: 3, “watch”: 4, “movies”: 5,”also”: 6, “football”: 7, “games”: 8,”Mary”: 9, “too”: 10}


上面的詞典中包含10個單詞, 每個單詞有唯一的索引, 那麼每個文字我們可以使用一個10維的向量來表示,向量中的元素是詞典中對應的詞語出現的頻數。如下所示:

[1, 2, 1, 1, 1, 0, 0, 0, 1, 1] 
[1, 1,1, 1, 0, 1, 1, 1, 0, 0]


該向量與原來文字中單詞出現的順序沒有關係,而是詞典中每個單詞在文字中出現的頻數。

第二個要介紹的是名為“霍夫曼樹”的資料結構,fastText的速度快,且不會受到不平衡分類問題影響的關鍵因素就是這個資料結構。

霍夫曼編碼樹,又稱最優二叉樹。是一類帶權路徑長度最短的樹。假設有n個權值{w1,w2,…,wn},如果構造一棵有n個葉子節點的二叉樹,而這n個葉子節點的權值是{w1,w2,…,wn},則所構造出的帶權路徑長度最小的二叉樹就被稱為霍夫曼樹。

帶權路徑長度:如果在一棵二叉樹中共有n個葉子節點,用Wi表示第i個葉子節點的權值,Li表示第i個葉子節點到根節點的路徑長度,則該二叉樹的帶權路徑長度:

WPL=W1∗L1+W2∗L2+...Wn∗LnWPL=W1∗L1+W2∗L2+...Wn∗Ln

霍夫曼樹的構建步驟如下: 
(1)將給定的n個權值看做n棵只有根節點(無左右孩子)的二叉樹,組成一個集合HT,每棵樹的權值為該節點的權值。 
(2)從集合HT中選出2棵權值最小的二叉樹,組成一棵新的二叉樹,其權值為這2棵二叉樹的權值之和。 
(3)將步驟2中選出的2棵二叉樹從集合HT中刪去,同時將步驟2中新得到的二叉樹加入到集合HT中。 
(4)重複步驟2和步驟3,直到集合HT中只含一棵樹,這棵樹便是霍夫曼樹。

感覺還雲裡霧裡?沒關係,小編來舉個簡單的例子你就明白了。假設給定如圖1的四個帶權重的節點A—D,結點下方為其對應的權重。

感覺還雲裡霧裡?沒關係,小編來舉個簡單的例子你就明白了。假設給定如圖1的四個帶權重的節點A—D,結點下方為其對應的權重。 

這裡寫圖片描述

圖1

首先選出權重最小的兩個節點作為圖2中新樹的左右子樹(新樹即右側由6、C、A組成的樹),新樹根節點權重為其左右子樹權重之和(即1+5=6)。 

這裡寫圖片描述

圖2


然後重複前一操作,從剩餘結點中選出最小的,與前一個樹的根節點組成新樹的左右結點,如圖3所示,新的根節點權重為其兩個子結點之和(10+6=16)。 

這裡寫圖片描述

圖3


在重複前面的操作,得到圖4的最終樹。

fastText的霍夫曼樹葉子結點對應為最終的label,可以看到,權重最大的,也就是權重最大的label,其深度最小,fastText 充分利用了這個性質,使得其速度得以提升。 

這裡寫圖片描述

圖4

Huffman編碼(霍夫曼編碼): 
對每個字元設計長度不等的編碼,讓出現較多的字符采用盡可能短的編碼。利用霍夫曼樹求得的用於通訊的二進位制編碼稱為霍夫曼編碼。 
樹中從根結點到每個葉子節點都有一條路徑,對路徑上的各分支約定指向左子樹的分支表示“0”碼,指向右子樹的分支表示“1”碼,取每條路徑上的“0”或“1”的序列作為各個葉子節點對應的字元編碼,即是霍夫曼編碼。以前面的例子為例,各路徑上的編碼如圖5所示。故A結點的編碼應當為111,B為10,C為110,D為0。D是權重最大的結點,換言之也就是出現最多的結點,其編碼最短,只有一個0,而權重最小的結點是A,其編碼為111,這樣的編碼方式完成了我們對節點編碼的需求。 

這裡寫圖片描述

圖5

fastText模型架構

fastText演算法是一種有監督的模型,與《前篇》中的CBOW架構很相似,其結構如圖6所示。《前篇》中的CBOW,通過上下文預測中間詞,而fastText則是通過上下文預測標籤(這個標籤就是文字的類別,是訓練模型之前通過人工標註等方法事先確定下來的)。如果小主在上一篇文章中已經對CBOW瞭解透徹了,可能到這裡你已經覺得fastText並沒有什麼新鮮玩意兒。事實確實如此,從模型架構上來說,沿用了CBOW的單層神經網路的模式,不過fastText的處理速度才是這個演算法的創新之處。

fastText模型的輸入是一個詞的序列(一段文字或者一句話),輸出是這個詞序列屬於不同類別的概率。在序列中的詞和片語構成特徵向量,特徵向量通過線性變換對映到中間層,再由中間層對映到標籤。fastText在預測標籤時使用了非線性啟用函式,但在中間層不使用非線性啟用函式。

圖 6 展示了一個有一個隱藏層的簡單模型。第一個權重矩陣w_1可以被視作某個句子的詞查詢表(詞表查詢是啥來著?去看看《前篇》中的那個矩陣相乘你就想起來了)。詞表徵被平均成一個文字表徵,然後其會被饋送入一個線性分類器。這個構架和《前篇》介紹的CBOW模型相似,只是中間詞(middle word)被替換成了標籤(label)。該模型將一系列單詞作為輸入併產生一個預定義類的概率分佈。我們使用一個softmax方程來計算這些概率。當資料量巨大時,線性分類器的計算十分昂貴,所以fastText使用了一個基於霍夫曼編碼樹的分層softmax方法。常用的文字特徵表示方法是詞袋模型,然而詞袋(BoW)中的詞順序是不變的,但是明確考慮該順序的計算成本通常十分高昂。作為替代,fastText使用n-gram獲取額外特徵來得到關於區域性詞順序的部分資訊,後文將詳細介紹。 

這裡寫圖片描述

圖6

層次softmax

Facebook聲稱fastText比其他學習方法要快得多,能夠訓練模型“在使用標準多核CPU的情況下10分鐘內處理超過10億個詞彙”,特別是與深度模型對比,fastText能將訓練時間由數天縮短到幾秒鐘。這樣的速度取決於什麼呢?模型架構上並沒有什麼本質革新,接下來就帶你“上高速”~

softmax函式

上一篇,我們已經介紹了這個函式。softmax函式實際是一個歸一化的指數函式: 

σ(z)j=ezj∑Kk=1ezkσ(z)j=ezj∑k=1Kezk


而softmax把一個k維的real value向量(a1,a2,a3,a4….)對映成一個(b1,b2,b3,b4….)其中bi是一個0-1的常數,然後可以根據bi的大小來進行多分類的任務,如取權重最大的一維。

分層softmax(Hierarchical softmax)

分層softmax的目的是降低softmax層的計算複雜度。 
二叉樹。Hierarchical softmax本質上是用層級關係替代了扁平化的softmax層,如圖1所示,每個葉子節點表示一個詞語(即霍夫曼樹的結構)。 

這裡寫圖片描述

圖7 Hierarchical softmax

我們可以把原來的softmax看做深度為1的樹,詞表V中的每一個詞語表示一個葉子節點。如果把softmax改為二叉樹結構,每個word表示葉子節點,那麼只需要沿著通向該詞語的葉子節點的路徑搜尋,而不需要考慮其它的節點。這就是為什麼fastText可以解決不平衡分類問題,因為在對某個節點進行計算時,完全不依賴於它的上一層的葉子節點(即權重大於它的葉結點),也就是數目較大的label不能影響數目較小的label(即圖5中B無法影響A和C)。

平衡二叉樹的深度是log2(|V|),因此,最多隻需要計算log2(|V|)個節點就能得到目標詞語的概率值。hierarchical softmax定義了詞表V中所有詞語的標準化概率分佈。

具體說來,當遍歷樹的時候,我們需要能夠計算左側分枝或是右側分枝的概率值。為此,給每個節點分配一個向量表示。與常規的softmax做法不同,這裡不是給每個輸出詞語w生成詞向量v_w^’,而是給每個節點n計算一個向量〖v﷩n﷩’〗。總共有|V|-1個節點,每個節點都有自己獨一無二的向量表示,H-Softmax方法用到的引數與常規的softmax幾乎一樣。於是,在給定上下文c時,就能夠計算節點n左右兩個分枝的概率: 

p(right|n,c=σ(hTvnT))p(right|n,c=σ(hTvnT))

上式與常規的softmax大致相同。現在需要計算h與樹的每個節點的向量v_n^’的內積,而不是與每個輸出詞語的向量計算。而且,只需要計算一個概率值,這裡就是偏向n節點右枝的概率值。相反的,偏向左枝的概率值是1- p(right│n,c)。

這裡寫圖片描述

圖8 Hierarchical softmax的計算過程(來自Hugo Lachorelle的YouTube課件)

如圖8所示,為了方便理解,這裡的葉子節點給出的依然是詞語,也就是CBOW的架構,fastText是相同的道理,只是將葉子節點替換為label即可。假設已知出現了詞語“the”、“dog”、“and”、“the”,則出現詞語“cat”的概率值就是在節點1向左偏的概率值、在節點2向右偏的概率以及在節點5向右偏的概率值的乘積。

值得注意的是,此方法只是加速了訓練過程,因為我們可以提前知道將要預測的詞語(以及其搜尋路徑)。在測試過程中,被預測詞語是未知的,仍然無法避免計算所有詞語的概率值。 
向量表示該節點的搜尋路徑,詞語“cat”的向量就是011。上文中提到平衡二叉樹的深度不超過log2(|V|)。若詞表的大小是|V|=10000,那麼搜尋路徑的平均長度就是13.3。

N-gram

常用的特徵是詞袋模型,在第一部分小編已經介紹過詞袋模型了。詞袋模型不考慮詞之間的順序,因此 fastText 還加入了 N-gram 特徵。“我愛你”的特徵應當是“我”、“愛”、“你”。那麼“你愛我”這句話的特徵和“我愛你”是一樣的,因為“我愛你”的bag(詞袋)中也是隻包含“你”、“愛”、“我”。

還是那句話——“我愛你”:如果使用2-gram,這句話的特徵還有 “我-愛”和“愛-你”,這兩句話“我愛你”和“你愛我”就能區別開來了,因為“你愛我”的2-gram的特徵還包括“你-愛”和“愛-我”,這樣就可以區分“你愛我”和“我愛你”了。為了提高效率,實務中會過濾掉低頻的 N-gram。否則將會嚴重影響速度。 
在fastText 中一個低維度向量與每個單詞都相關。隱藏表徵在不同類別所有分類器中進行共享,使得文字資訊在不同類別中能夠共同使用。這類表徵被稱為詞袋(bag of words)(此處忽視詞序)。在 fastText中也使用向量表徵單詞 n-gram來將區域性詞序考慮在內,這對很多文字分類問題來說十分重要。

fastText演算法實現

這裡提醒讀者,fastText在Python2和Python3中都可以使用,已有了現成的包,但只支援Linux和mac系統,windows暫時還不支援fastText。本例使用的環境是linux-ubuntu16.04+Python3+JupyterNotebook的組合,讀者當然可以使用其他IDE或是使用Python2,都是完全沒有問題的。只需要在終端使用語句pip install fasttext(Python2)或是pip3 install fasttext進行安裝即可。

這裡寫圖片描述

圖9 分詞後資料樣例

使用logging可以檢視程式執行日誌。fasttext.supervised()的第一個引數為訓練集,即用來擬合模型的資料,第二個引數為模型儲存的絕對路徑,第三個為文字與標籤的分隔符;訓練好模型後通過load_model載入模型,對訓練集使用test方法則可以在測試集上使用模型,則會得到模型在測試集上的準確率和召回率,可以看到模型的準確率和召回率是非常高的,而且對於這個近400Mb的訓練集,擬合模型只花費了60秒左右(小編的電腦為8GB記憶體),速度是非常可觀的。

這裡寫圖片描述

圖10 建立模型

fastText演算法通過了兩篇的講解,相比聰明的你已經掌握了演算法原理,關於fastText演算法到這裡就要告一段落了,熟悉了原理和思想,接下來小主可以去找些有趣的文字做一些有趣的事情了,與fastText一起飈車吧!