【NLP】fastText词向量与文本分类工具
一、簡介
fastText 是 Facebook 于2016年開源的一個詞向量訓練與文本分類工具,其典型應用場景是“無監督的詞向量學習”和“有監督的文本分類”。fastText 提供簡單而高效的文本分類和詞表征學習方法,性能比肩深度學習但速度優勢明顯。在文本分類任務中,fastText(淺層網絡)往往能取得和深度學習分類器相媲美的精度,卻在訓練和預測時間上快深度網絡許多數量級。在標準的多核 CPU 上,10億詞級別語料庫的詞向量能夠在10分鐘以內訓練完成,在1分鐘之內能夠分類有著31萬類別的50多萬條句子。
github地址:https://github.com/facebookresearch/fastText ? ?star:22.9k
論文及地址:
Bag of Tricks for Efficient Text Classification:https://arxiv.org/abs/1607.01759
Enriching Word Vectors with Subword Information:https://arxiv.org/abs/1607.04606
FastText.zip: Compressing text classification models:https://arxiv.org/abs/1612.03651
二、模型架構
介紹模型之前,我們先稍微聊一點八卦。fastText 的其中一個作者是 Thomas Mikolov。熟悉 word2vec 的同學應該對這個名字很熟悉,正是他當年在 Google 帶了一個團隊倒騰出來了 word2vec,很好的解決了傳統詞袋表示的缺點,極大地推動了 NLP 領域的發展。后來這位大哥跳槽去了 Facebook,才有了現在的 fastText。從“血緣”角度來看,fastText 和 word2vec 可以說是一脈相承。
fastText 中詞向量的無監督訓練過程使用的是 word2vec 中的 CBOW 架構和 Skip-gram 架構。在文本分類任務中,fastText 模型架構和 word2vec 中的 CBOW 很相似,不同之處在于 fastText 最終預測的是文檔類別標簽(label)而 CBOW 預測的是中間詞(middle word),即模型架構類似但模型的任務有所不同。如下為 CBOW 的結構:
word2vec 將單詞間的上下文關系轉化為多分類任務,通過訓練邏輯回歸模型得到單詞的詞向量,每次多分類任務的類別數量為詞庫大小 。通常的文本語料中,詞庫單詞少則數萬、多則上百萬,直接訓練多分類邏輯回歸并不現實。word2vec 中提供了兩種針對大規模多分類問題的優化手段:negative sampling 和 hierarchical softmax。在訓練中,negative sampling 對于當前單詞只隨機采樣少量負樣本,從而減輕了計算量;hierarchical softmax 根據詞庫中單詞的詞頻(count)構建一棵霍夫曼樹,從根結點到葉子結點的路徑可以表示為一系列二分類器,一次多分類計算的復雜度從 降低到了 , 為詞向量的維度。
上圖為 fastText 模型架構,此架構展示的是文本分類任務過程,沒有展示詞向量的訓練過程。其中 表示文檔或句子中的單詞和 n-gram 向量,整個文檔可以使用所有單詞和 n-gram 向量累加后的均值表示,即 ,然后經過一個線性分類器得到輸出層的 label。對比 word2vec 中的 CBOW 模型,可以發現兩個模型非常相似,只不過 fastText 模型最后預測的是文檔的 label,而 CBOW 模型預測的是窗口中間的詞,前者是有監督的學習,后者是無監督的學習。另外,fastText 分類模型的輸入層為文檔中的所有詞和 n-gram,而 CBOW 模型的輸入層只包括當前窗口內除中心詞的所有詞,沒有 n-gram 和 subword 信息。
三、數學原理
fastText 本質上可以看成是一個淺層的神經網絡,因此其前向傳播(forward propogation)過程可描述如下:
其中 表示從隱藏層到輸出層的權重矩陣, 是輸出層的輸出向量。由于模型需要預測文檔屬于某個類別的概率,因此需要對輸出向量加一個 softmax 層,損失函數可以定義為:
當文檔類別數很多時,softmax 層的計算會比較耗時,為了加快訓練過程,fastText 同樣采用了和word2vec 類似的方法。一種方法是使用 hierarchical softmax,當類別數為 ,詞向量維度為 時,計算復雜度可以從 降到 。另一種方法是采用 negative sampling,即每次從除當前 label 外的其他 label 中采樣幾個作為負樣本,訓練邏輯回歸模型。
Hierarchical softmax
fastText 中基于 hierarchical softmax 的文本分類結構如下圖所示:
輸出層對應一棵二叉樹,它是以訓練語料中的所有文檔標簽為葉子結點,以各個標簽下的文檔數量為權值構造出來的霍夫曼樹。在這棵 Huffman 樹中,葉子結點共 個,分別表示語料中的文檔類別標簽,非葉子結點 個,每個非葉子結點對應一個二分類所需的權重向量 ??紤] Huffman 樹中的某個葉子結點,假設它對應語料中第 個類別,記
:從根結點出發到達類別 對應葉子結點的路徑。
:路徑 中包含的結點個數。
:路徑 中的所有結點,其中第一個表示根結點,最后一個表示類別 對應的葉子結點。
類別 對應葉子結點的霍夫曼編碼:,其中 表示路徑 中第 個結點對應的編碼(根結點不對應編碼)。
:路徑 中每個非葉子結點對應的二分類權重。
對于訓練語料中的每個類別 ,Huffman 樹中必然存在一條從根結點到類別 對應葉子結點的路徑 (且這條路徑是唯一的)。路徑上存在 個分支,將每個分支看成一次二分類,每一次二分類就產生一個概率,將這些概率連乘起來,就是單個樣本的似然函數 ,可表示為:
其中 為文檔 的向量表示,在前文中已經介紹過。上式中:
因此
整個訓練語料的對數似然函數可以表示為:
損失函數為負的對數似然函數,即
fastText 中使用隨機梯度下降法最小化上述損失函數。
Negative sampling
fastText 中使用 Negative Sampling(簡稱為NEG)主要是為了提高訓練速度。與 Hierarchical Softmax 相比,NEG 不再使用復雜的 Huffman 樹,而是利用相對簡單的隨機負采樣,能大幅度提高性能,因此可作為 Hierarchical Softmax 的一種替代。
對于一個給定的文檔類別 ,如何生成它對應的負樣本集合 呢?訓練語料中不同類別標簽的文檔數量有多有少,對于那些文檔數量多的類別,被選為負樣本的概率就應該比較大;反之,對于那些低頻類別標簽,被選為負樣本的概率就應該比較小。這本質上是一個帶權采樣問題,fastText 中使用如下方法初始化負采樣中需要用到的查找表:
std::vector<int32_t>?negative_tables(const?std::vector<int64_t>&?targetCounts,const?int32_t?NEGATIVE_TABLE_SIZE?=?10000000)?{float?z?=?0.0;std::vector<int32_t>?negatives;for?(size_t?i?=?0;?i?<?targetCounts.size();?i++)?{z?+=?pow(targetCounts[i],?0.5);}for?(size_t?i?=?0;?i?<?targetCounts.size();?i++)?{float?c?=?pow(targetCounts[i],?0.5);for?(size_t?j?=?0;?j?<?c?*?NEGATIVE_TABLE_SIZE?/?z;?j++)?{negatives.push_back(i);}}return?negatives; }在實際進行類別 的負采樣時,首先隨機生成一個 ~ 之間的正整數 ,然后判斷查找表中對應的 是否等于類別 ,如果相等,則重復上述過程,直至生成一個不為 的負類別標簽。
基于 negative sampling 方法的單個樣本似然函數可以表示為:
其中 為文檔 的向量表示, 為類別 對應的權重向量, 為對類別 進行負采樣的負標簽集合。上式中:
整個訓練語料的損失函數可以表示為:
其中 為語料中文檔 的類別。fastText 中使用隨機梯度下降法最小化上述損失函數。
N-gram特征
文本分類任務中常用的特征提取方法是詞袋模型(Bag-of-words),但詞袋模型不能考慮詞與詞之間的順序,丟失了詞序信息。為了彌補這個不足,fastText 增加了 N-gram 的特征,其 N-gram 特征包括兩種:(1) 詞與詞之間的 n-gram 特征;(2) 單個詞內的 subword 特征,即字符級別的 n-gram 特征。舉個例子來說,假設某篇文檔包含如下幾個詞:
machine learning and data mining algorithms對于詞與詞之間的 n-gram 特征
相應的 bigram 詞組為:machine learning,learning and,and data,data mining,mining algorithms;
相應的 trigram 詞組為:machine learning and,learning and data,and data mining,data mining algorithms
對于字符級別的 n-gram 特征,以 machine 為例,假設 ,可以得到 machine 的6個字符級 4-gram 如下:<mac,mach,achi,chin,hine,ine>。
在文本分類任務中,文檔的向量表示計算為文檔內每個單詞、詞與詞之間的 n-gram 以及單個詞內的 subwords 的向量求和后取平均。在詞向量任務中,單詞的向量表示計算為該單詞以及其 subwords 的向量求和后取平均。與 word2vec 相比,fastText 在詞向量訓練時融入了 subword 信息。通過隨機梯度下降法,fastText 可以同時學到單詞的向量表示和兩種 n-gram 的向量表示。
具體實現上,由于 n-gram 的量遠比單詞數大的多,完全存下所有的 n-gram 也不現實。fastText 采用了 Hash 桶的方式,把所有的 n-gram 都哈希到 個桶中,哈希到同一個桶的所有 n-gram 共享一個 embedding vector。如下圖所示:
圖中 是 Embedding 矩陣,每行代表一個 word 或 n-gram 的表示向量,其中前 行是 word embeddings,后 行是 n-gram embeddings。每個 n-gram 經哈希函數哈希到 ~ 的位置,得到對應的 embedding 向量。用哈希的方式既能保證查找是 的效率,又能把內存消耗控制在 范圍內。不過這種方法潛在的問題是存在哈希沖突,不同的 n-gram 可能會共享同一個 embedding。如果桶大小取的足夠大,這種影響會很小。
fastText 中使用 n-gram 特征有如下優點:
為罕見的單詞生成更好的詞向量。根據上面的字符級別的 n-gram 來說,即使這個單詞出現的次數很少,但是組成單詞的字符和其他單詞有共享的部分,因此這一點可以優化生成的單詞向量。
在詞匯單詞中,即使單詞沒有出現在訓練語料庫中,仍然可以根據字符級 n-gram 的向量構造出單詞的詞向量。
n-gram 特征可以讓模型學習到局部單詞順序的部分信息,如果不考慮 n-gram 則便是取每個單詞,這樣無法考慮到詞序所包含的信息,也可理解為上下文信息,因此通過 n-gram 的方式關聯相鄰的幾個詞,會讓模型在訓練時保持詞序信息。
四、文本分類
首先將 fastText 代碼庫克隆到本地,進入代碼庫,并進行編譯:
編譯完成后生成 fasttext 可執行文件,運行 ./fasttext 命令后得到:
fasttext 支持使用有監督的語料訓練一個文本分類器,使用無監督的語料訓練 cbow 和 skipgram 詞向量模型。運行代碼倉庫中 classification-example.sh 的如下部分代碼,下載文本分類需要用到的訓練數據和測試數據,并進行預處理:
myshuf()?{perl?-MList::Util=shuffle?-e?'print?shuffle(<>);'?"$@"; }normalize_text()?{tr?'[:upper:]'?'[:lower:]'?|?sed?-e?'s/^/__label__/g'?|?\sed?-e?"s/'/?'?/g"?-e?'s/"//g'?-e?'s/\./?\.?/g'?-e?'s/<br?\/>/?/g'?\-e?'s/,/?,?/g'?-e?'s/(/?(?/g'?-e?'s/)/?)?/g'?-e?'s/\!/?\!?/g'?\-e?'s/\?/?\??/g'?-e?'s/\;/?/g'?-e?'s/\:/?/g'?|?tr?-s?"?"?|?myshuf }RESULTDIR=result DATADIR=datamkdir?-p?"${RESULTDIR}" mkdir?-p?"${DATADIR}"if?[?!?-f?"${DATADIR}/dbpedia.train"?] thenwget?-c?"https://github.com/le-scientifique/torchDatasets/raw/master/dbpedia_csv.tar.gz"?-O?"${DATADIR}/dbpedia_csv.tar.gz"tar?-xzvf?"${DATADIR}/dbpedia_csv.tar.gz"?-C?"${DATADIR}"cat?"${DATADIR}/dbpedia_csv/train.csv"?|?normalize_text?>?"${DATADIR}/dbpedia.train"cat?"${DATADIR}/dbpedia_csv/test.csv"?|?normalize_text?>?"${DATADIR}/dbpedia.test" fi預處理后的訓練數據和測試數據位于新建的 data 文件夾下,分別對應 dbpedia.train 和 dbpedia.test,其格式如下:
每行表示一個樣本,行首是該樣本的類別標簽:__label__3 形式。使用如下命令訓練一個文本分類器:
./fasttext?supervised?-input?"${DATADIR}/dbpedia.train"?-output?"${RESULTDIR}/dbpedia"?-dim?10?-lr?0.1?-wordNgrams?2?-minCount?1?-bucket?10000000?-epoch?5?-thread?4其中 DATADIR 和 RESULTDIR 在前面代碼中已經定義,-input 參數為如上形式的訓練數據文件,-output 參數為模型和詞向量的保存路徑,-dim 參數為詞向量的維度,-wordNgrams 參數為加入詞的幾階 ngram 信息,-epoch 參數為迭代次數。訓練過程如下所示:
訓練完成后,在 -output 參數對應的路徑下會有一個 .bin 模型文件和 .vec 詞向量文件。使用如下命令在測試數據集上評估分類模型效果:
./fasttext?test-label?"${RESULTDIR}/dbpedia.bin"?"${DATADIR}/dbpedia.test"輸出模型在測試數據集上每個類別的 Precision、Recall 和 F1-Score 信息如下:
可以看出 fastText 在 dbpedia 數據集上訓練得到的文本分類模型效果很好而且速度很快?;谟柧毢玫姆诸惸P?#xff0c;使用如下命令進行輸入文本的類別預測:
./fasttext?predict?"${RESULTDIR}/dbpedia.bin"?"${DATADIR}/dbpedia.test"?>?"${RESULTDIR}/dbpedia.test.predict"dbpedia.test.predict 文件為模型預測得到的類別標簽文件。
往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯黃海廣老師《機器學習課程》視頻課本站qq群851320808,加入微信群請掃碼:
總結
以上是生活随笔為你收集整理的【NLP】fastText词向量与文本分类工具的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring Boot报错 之五种(不打
- 下一篇: 怎么将手机QQ浏览器里面的文章分享给QQ