當前位置:
首頁 > 最新 > 技術乾貨 fastText原理及實踐

技術乾貨 fastText原理及實踐

fastText是Facebook於2016年開源的一個詞向量計算和文本分類工具,在學術上並沒有太大創新。但是它的優點也非常明顯,在文本分類任務中,fastText(淺層網路)往往能取得和深度網路相媲美的精度,卻在訓練時間上比深度網路快許多數量級。在標準的多核CPU上, 能夠訓練10億詞級別語料庫的詞向量在10分鐘之內,能夠分類有著30萬多類別的50多萬句子在1分鐘之內。

本文首先會介紹一些預備知識,比如softmax、ngram等,然後簡單介紹word2vec原理,之後來講解fastText的原理,並著手使用keras搭建一個簡單的fastText分類器,最後,我們會介紹fastText在達觀數據的應用。

NO.1

fastText原理

及實踐

預備知識

1

Softmax回歸

Softmax回歸(Softmax Regression)又被稱作多項邏輯回歸(multinomial logistic regression),它是邏輯回歸在處理多類別任務上的推廣。

在邏輯回歸中, 我們有m個被標註的樣本:,其中。因為類標是二元的,所以我們有。我們的假設(hypothesis)有如下形式:

代價函數(cost function)如下:

在Softmax回歸中,類標是大於2的,因此在我們的訓練集

中,。給定一個測試輸入x,我們的假設應該輸出一個K維的向量,向量內每個元素的值表示x屬於當前類別的概率。具體地,假設形式如下:

代價函數如下:

其中1{·}是指示函數,即1=1,1=0

既然我們說Softmax回歸是邏輯回歸的推廣,那我們是否能夠在代價函數上推導出它們的一致性呢?當然可以,於是:

可以看到,邏輯回歸是softmax回歸在K=2時的特例。

2

分層Softmax

你可能也發現了,標準的Softmax回歸中,要計算y=j時的Softmax概率:,我們需要對所有的K個概率做歸一化,這在y很大時非常耗時。於是,分層Softmax誕生了,它的基本思想是使用樹的層級結構替代扁平化的標準Softmax,使得在計算時,只需計算一條路徑上的所有節點的概率值,無需在意其它的節點。

下圖是一個分層Softmax示例:

樹的結構是根據類標的頻數構造的霍夫曼樹。K個不同的類標組成所有的葉子節點,K-1個內部節點作為內部參數,從根節點到某個葉子節點經過的節點和邊形成一條路徑,路徑長度被表示為。於是,就可以被寫成:

其中:

表示sigmoid函數;

表示n節點的左孩子;

是一個特殊的函數,被定義為:

是中間節點的參數;X是Softmax層的輸入。

上圖中,高亮的節點和邊是從根節點到的路徑,路徑長度

可以被表示為:

於是,從根節點走到葉子節點,實際上是在做了3次二分類的邏輯回歸。

通過分層的Softmax,計算複雜度一下從K降低到logK。

3

n-gram特徵

在文本特徵提取中,常常能看到n-gram的身影。它是一種基於語言模型的演算法,基本思想是將文本內容按照位元組順序進行大小為N的滑動窗口操作,最終形成長度為N的位元組片段序列。看下面的例子:

我來到達觀數據參觀

相應的bigram特徵為:

我來 來到 到達 達觀 觀數 數據 據參 參觀

相應的trigram特徵為:

我來到 來到達 到達觀 達觀數 觀數據 數據參 據參觀

注意一點:n-gram中的gram根據粒度不同,有不同的含義。它可以是字粒度,也可以是詞粒度的。上面所舉的例子屬於字粒度的n-gram,詞粒度的n-gram看下面例子:

我 來到 達觀數據 參觀

相應的bigram特徵為:

我/來到 來到/達觀數據 達觀數據/參觀

相應的trigram特徵為:

我/來到/達觀數據 來到/達觀數據/參觀

n-gram產生的特徵只是作為文本特徵的候選集,你後面可能會採用信息熵、卡方統計、IDF等文本特徵選擇方式篩選出比較重要特徵。

NO.2

fastText原理

及實踐

Word2vec

你可能要問,這篇文章不是介紹fastText的么,怎麼開始介紹起了word2vec?

最主要的原因是word2vec的CBOW模型架構和fastText模型非常相似。於是,你看到facebook開源的fastText工具不僅實現了fastText文本分類工具,還實現了快速詞向量訓練工具。word2vec主要有兩種模型:skip-gram 模型和CBOW模型,這裡只介紹CBOW模型,有關skip-gram模型的內容請參考達觀另一篇技術文章:

1

模型架構

CBOW模型的基本思路是:用上下文預測目標辭彙。架構圖如下所示:

輸入層由目標辭彙y的上下文單片語成,是被onehot編碼過的V維向量,其中V是辭彙量;隱含層是N維向量h;輸出層是被onehot編碼過的目標詞y。輸入向量通過維的權重矩陣W連接到隱含層;隱含層通過維的權重矩陣連接到輸出層。因為詞庫V往往非常大,使用標準的softmax計算相當耗時,於是CBOW的輸出層採用的正是上文提到過的分層Softmax。

2

前向傳播

輸入是如何計算而獲得輸出呢?先假設我們已經獲得了權重矩陣和(具體的推導見第3節),隱含層h的輸出的計算公式:

即:隱含層的輸出是C個上下文單詞向量的加權平均,權重為W。

接著我們計算輸出層的每個節點:

這裡是矩陣的第j列,最後,將作為softmax函數的輸入,得到:

3

反向傳播學習權重矩陣

在學習權重矩陣和過程中,我們首先隨機產生初始值,然後feed訓練樣本到我們的模型,並觀測我們期望輸出和真實輸出的誤差。接著,我們計算誤差關於權重矩陣的梯度,並在梯度的方向糾正它們。

首先定義損失函數,objective是最大化給定輸入上下文,target單詞的條件概率。因此,損失函數為:

這裡,表示目標單詞在詞庫V中的索引。

如何更新權重?

我們先對E關於求導:

函數表示:

於是,的更新公式:

如何更新權重W?

我們首先計算E關於隱含層節點的導數:

然後,E關於權重的導數為:

於是,的更新公式:

NO.3

fastText原理

及實踐

fastText分類

終於到我們的fastText出場了。這裡有一點需要特別注意,一般情況下,使用fastText進行文本分類的同時也會產生詞的embedding,即embedding是fastText分類的產物。除非你決定使用預訓練的embedding來訓練fastText分類模型,這另當別論。

1

字元級別的n-gram

word2vec把語料庫中的每個單詞當成原子的,它會為每個單詞生成一個向量。這忽略了單詞內部的形態特徵,比如:「apple」 和「apples」,「達觀數據」和「達觀」,這兩個例子中,兩個單詞都有較多公共字元,即它們的內部形態類似,但是在傳統的word2vec中,這種單詞內部形態信息因為它們被轉換成不同的id丟失了。

為了克服這個問題,fastText使用了字元級別的n-grams來表示一個單詞。對於單詞「apple」,假設n的取值為3,則它的trigram有:

「」

其中,表示後綴。於是,我們可以用這些trigram來表示「apple」這個單詞,進一步,我們可以用這5個trigram的向量疊加來表示「apple」的詞向量。

這帶來兩點好處:

1. 對於低頻詞生成的詞向量效果會更好。因為它們的n-gram可以和其它詞共享。

2. 對於訓練詞庫之外的單詞,仍然可以構建它們的詞向量。我們可以疊加它們的字元級n-gram向量。

2

模型架構

之前提到過,fastText模型架構和word2vec的CBOW模型架構非常相似。下面是fastText模型架構圖:

注意:此架構圖沒有展示詞向量的訓練過程。可以看到,和CBOW一樣,fastText模型也只有三層:輸入層、隱含層、輸出層(Hierarchical Softmax),輸入都是多個經向量表示的單詞,輸出都是一個特定的target,隱含層都是對多個詞向量的疊加平均。

不同的是,CBOW的輸入是目標單詞的上下文,fastText的輸入是多個單詞及其n-gram特徵,這些特徵用來表示單個文檔;CBOW的輸入單詞被onehot編碼過,fastText的輸入特徵是被embedding過;CBOW的輸出是目標辭彙,fastText的輸出是文檔對應的類標。

值得注意的是,fastText在輸入時,將單詞的字元級別的n-gram向量作為額外的特徵;在輸出時,fastText採用了分層Softmax,大大降低了模型訓練時間。這兩個知識點在前文中已經講過,這裡不再贅述。

fastText相關公式的推導和CBOW非常類似,這裡也不展開了。

3

核心思想

現在拋開那些不是很討人喜歡的公式推導,來想一想fastText文本分類的核心思想是什麼?

仔細觀察模型的後半部分,即從隱含層輸出到輸出層輸出,會發現它就是一個softmax線性多類別分類器,分類器的輸入是一個用來表徵當前文檔的向量;模型的前半部分,即從輸入層輸入到隱含層輸出部分,主要在做一件事情:生成用來表徵文檔的向量。那麼它是如何做的呢?疊加構成這篇文檔的所有詞及n-gram的詞向量,然後取平均。疊加詞向量背後的思想就是傳統的詞袋法,即將文檔看成一個由詞構成的集合。

於是fastText的核心思想就是:將整篇文檔的詞及n-gram向量疊加平均得到文檔向量,然後使用文檔向量做softmax多分類。這中間涉及到兩個技巧:字元級n-gram特徵的引入以及分層Softmax分類。

4

關於分類效果

還有個問題,就是為何fastText的分類效果常常不輸於傳統的非線性分類器?

假設我們有兩段文本:

我 來到 達觀數據

俺 去了 達而觀信息科技

這兩段文本意思幾乎一模一樣,如果要分類,肯定要分到同一個類中去。但在傳統的分類器中,用來表徵這兩段文本的向量可能差距非常大。傳統的文本分類中,你需要計算出每個詞的權重,比如tfidf值, 「我」和「俺」 算出的tfidf值相差可能會比較大,其它詞類似,於是,VSM(向量空間模型)中用來表徵這兩段文本的文本向量差別可能比較大。

但是fastText就不一樣了,它是用單詞的embedding疊加獲得的文檔向量,詞向量的重要特點就是向量的距離可以用來衡量單詞間的語義相似程度,於是,在fastText模型中,這兩段文本的向量應該是非常相似的,於是,它們很大概率會被分到同一個類中。

使用詞embedding而非詞本身作為特徵,這是fastText效果好的一個原因;另一個原因就是字元級n-gram特徵的引入對分類效果會有一些提升。

NO.4

fastText 原理

及實踐

手寫一個fastText

keras是一個抽象層次很高的神經網路API,由python編寫,底層可以基於Tensorflow、Theano或者CNTK。它的優點在於:用戶友好、模塊性好、易擴展等。所以下面我會用keras簡單搭一個fastText的demo版,生產可用的fastText請移步https://github.com/facebookresearch/fastText。

如果你弄懂了上面所講的它的原理,下面的demo對你來講應該是非常明了的。

為了簡化我們的任務:

1. 訓練詞向量時,我們使用正常的word2vec方法,而真實的fastText使用了字元級別的n-gram間接產生詞向量;

2. 我們的輸出層使用簡單的softmax分類,而真實的fastText使用的是Hierarchical Softmax。

首先定義幾個常量:

VOCAB_SIZE = 2000

EMBEDDING_DIM =100

MAX_WORDS = 500

CLASS_NUM = 5

VOCAB_SIZE表示辭彙表大小,這裡簡單設置為2000;

EMBEDDING_DIM表示經過embedding層輸出,每個詞被分散式表示的向量的維度,這裡設置為100。比如對於「達觀」這個詞,會被一個長度為100的類似於[ 0.97860014, 5.93589592, 0.22342691, -3.83102846, -0.23053935, …]的實值向量來表示;

MAX_WORDS表示一篇文檔最多使用的詞個數,因為文檔可能長短不一(即詞數不同),為了能feed到一個固定維度的神經網路,我們需要設置一個最大詞數,對於詞數少於這個閾值的文檔,我們需要用「未知詞」去填充。比如可以設置辭彙表中索引為0的詞為「未知詞」,用0去填充少於閾值的部分;

CLASS_NUM表示類別數,多分類問題,這裡簡單設置為5。

模型搭建遵循以下步驟:

1.添加輸入層(embedding層)。Embedding層的輸入是一批文檔,每個文檔由一個辭彙索引序列構成。例如:[10, 30, 80, 1000] 可能表示「我 昨天 來到 達觀數據」這個短文本,其中「我」、「昨天」、「來到」、「達觀數據」在辭彙表中的索引分別是10、30、80、1000;Embedding層將每個單詞映射成EMBEDDING_DIM維的向量。於是:input_shape=(BATCH_SIZE, MAX_WORDS), output_shape=(BATCH_SIZE,MAX_WORDS, EMBEDDING_DIM);

2.添加隱含層(投影層)。投影層對一個文檔中所有單詞的向量進行疊加平均。keras提供的GlobalAveragePooling1D類可以幫我們實現這個功能。這層的input_shape是Embedding層的output_shape,這層的output_shape=( BATCH_SIZE, EMBEDDING_DIM);

3.添加輸出層(softmax層)。真實的fastText這層是Hierarchical Softmax,因為keras原生並沒有支持Hierarchical Softmax,所以這裡用Softmax代替。這層指定了CLASS_NUM,對於一篇文檔,輸出層會產生CLASS_NUM個概率值,分別表示此文檔屬於當前類的可能性。這層的output_shape=(BATCH_SIZE, CLASS_NUM)

4.指定損失函數、優化器類型、評價指標,編譯模型。損失函數我們設置為categorical_crossentropy,它就是我們上面所說的softmax回歸的損失函數;優化器我們設置為SGD,表示隨機梯度下降優化器;評價指標選擇accuracy,表示精度。

用訓練數據feed模型時,你需要:

1.將文檔分好詞,構建辭彙表。辭彙表中每個詞用一個整數(索引)來代替,並預留「未知詞」索引,假設為0;

2.對類標進行onehot化。假設我們文本數據總共有3個類別,對應的類標分別是1、2、3,那麼這三個類標對應的onehot向量分別是[1, 0,

0]、[0, 1, 0]、[0, 0, 1];

3.對一批文本,將每個文本轉化為詞索引序列,每個類標轉化為onehot向量。就像之前的例子,「我 昨天 來到 達觀數據」可能被轉化為[10, 30,

80, 1000];它屬於類別1,它的類標就是[1, 0, 0]。由於我們設置了MAX_WORDS=500,這個短文本向量後面就需要補496個0,即[10, 30, 80, 1000, 0, 0, 0, …, 0]。因此,batch_xs的 維度為( BATCH_SIZE,MAX_WORDS),batch_ys的維度為(BATCH_SIZE, CLASS_NUM)。

下面是構建模型的代碼,數據處理、feed數據到模型的代碼比較繁瑣,這裡不展示。

NO.5

fastText原理

及實踐

fastText在達觀數據的應用

fastText作為誕生不久的詞向量訓練、文本分類工具,在達觀得到了比較深入的應用。主要被用在以下兩個系統:

1. 同近義詞挖掘。Facebook開源的fastText工具也實現了詞向量的訓練,達觀基於各種垂直領域的語料,使用其挖掘出一批同近義詞;

2. 文本分類系統。在類標數、數據量都比較大時,達觀會選擇fastText 來做文本分類,以實現快速訓練預測、節省內存的目的。

A

BOUT AUTHOR

關於作者

王江,達觀數據自然語言處理工程師,負責達觀NLP底層開發、私有化應用系統開發等工作。主要參與大型系統的開發,對機器學習、NLP等領域有濃厚興趣。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達觀數據 的精彩文章:

達觀數據CEO陳運文獲品途NBI商業影響力新銳人物TOP50

TAG:達觀數據 |