Last Updated on 2021-06-22 by Clay
FastText 是由 Facebook AI Research Lab (FAIR) 所開發的『詞嵌入』以及『文本分類』,支援 294 種語言,並且使用類神經網路訓練詞嵌入模型。
基本上 FastText 的演算法是基於以下這兩篇論文:
不過介紹了這麼多,今天我主要的目的是要介紹如何在 Python 中透過 Gensim 套件快速地調用 FastText 訓練一個 Word Embedding 的模型。基本上流程都與 Gensim 中本來訓練 Word2Vec 極度相像。
以下就直接來看程式碼。值得一提的是,由於我之前寫過使用 Gensim 訓練 Word2Vec 模型,所以有部份相同的流程我是直接從那邊抄來的 XDD
安裝 Gensim
首先,如果你的環境裡沒有 Gensim,使用以下指令安裝:
pip3 install gensim
下載 WIKI 語料
這裡以 Wiki 上的中文資料為訓練語料,Wiki 上的資料可是相當優秀的。不僅量多、而且詞彙涵蓋範圍廣,可以應用在許多不同的任務上。
可以從這個網址找到下載處:https://zh.wikipedia.org/wiki/Wikipedia:%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%8B%E8%BD%BD
進入之後可以直接選擇一個日期,那是不同時間點的資料備份。
比如說我選擇了 20200101 這個時間點的資料,那麼,我要下載的資料則為:zhwiki-20200101-pages-articles-multistream.xml.bz2
要注意的是,你的日期可能與我不同,不過同樣都是這份檔案。
下載之後不用解壓縮,可以使用 Gensim 裡的工具直接提取文章。
WikiCorpus
WikiCorpus 是 Gensim 裡面的一個模組,專門用於清理 Wiki 資料庫中語料不必要的標籤,使其恢復成乾淨的文本。
# coding: utf-8 """ Extracted the content in the wiki_database """ from gensim.corpora import WikiCorpus # Load data wiki_corpus = WikiCorpus('../data/zhwiki-latest-pages-articles-multistream.xml.bz2', dictionary={}) # Save data with open('wiki_text.txt', 'w', encoding='utf-8') as f: print('Start to preprocess.') for times, text in enumerate(wiki_corpus.get_texts()): f.write(' '.join(text)+'\n') if (times+1) % 10000 == 0: print(times+1)
順帶一提,WikiCorpus() 函式當中的路徑為我下載的語料資料,你的名稱可能與我不同、也需要對應到你下載的路徑。
儲存之後的效果應如下:
斷詞
『斷詞』這項工作指的是文本分成以『詞』為單位的句子。斷詞的工具有很多種,基本上可以參考我之前寫過的:
如果想要對繁體中文斷詞效果最好,首推 CKIP;如果是要斷詞速度的話,那非 Jieba 莫屬。在這裡以 Jieba 示範。
(註:Wiki 的資料當中許多地方是簡繁混雜的,可以考慮使用 OpenCC 這項工具來轉換。詳細的作法可以參閱我之前撰寫過的《中文繁簡轉換的便利工具 —— OpenCC》)
# coding: utf-8 """ Tokenize """ import jieba from opencc import OpenCC # Initial cc = OpenCC('s2t') # Tokenize with open('wiki_text_seg.txt', 'w', encoding='utf-8') as new_f: with open('wiki_text.txt', 'r', encoding='utf-8') as f: for data in f: data = cc.convert(data) data = jieba.cut(data) data = [word for word in data if word != ' '] data = ' '.join(data) new_f.write(data)
斷詞結果展示如下:
歐幾
裏
得
西元前
三世
紀的
古希臘
數學家
現在
被
認為
是
幾何
之父
此畫
為拉斐爾
的
作品
雅典
學院
數學
是
利用
…
最後,終於來到呼叫 FastText 來訓練模型了。
使用 FastText 訓練模型
# coding: utf-8 from gensim.models import word2vec, fasttext # Settings seed = 666 sg = 0 window_size = 10 vector_size = 100 min_count = 1 workers = 8 epochs = 5 batch_words = 10000 # Train train_data = word2vec.LineSentence('wiki_text_seg.txt') model = fasttext.FastText( train_data, min_count=min_count, size=vector_size, workers=workers, iter=epochs, window=window_size, sg=sg, seed=seed, batch_words=batch_words, ) model.save('fasttext.model')
這裡也解釋一下模型中各個參數的意義:
- seed: 亂數種子
- sg: Word2Vec 有兩種算法,CBOW 以及 Skip-gram,這裡選擇了訓練比較快的 CBOW
- window_size: 周圍詞彙要看多少範圍
- size: 轉成向量的維度
- min_count: 詞頻少於 min_count 之詞彙不會參與訓練
- workers: 訓練的並行數量
- iter: 訓練的迭代次數
- batch_words:每次給予多少詞彙量訓練
訓練結束以後,我將模型儲存為 "fasttext.model"。
測試模型效果
# coding: utf-8 """ Test the w2v model """ from gensim.models import word2vec # Load the model model = word2vec.Word2Vec.load('models/fasttext.model') # Test print(model['生物'].shape) for item in model.most_similar('生物'): print(item) model.save('fasttext.model')
Output:
(100,)
('若好', 0.9359757900238037)
('身半', 0.9298930764198303)
('過金', 0.9281899929046631)
('低等生物', 0.9252755641937256)
('腐生物', 0.9232699275016785)
('過金魅', 0.9228056073188782)
('生物能', 0.9225305914878845)
('捉酸蟲', 0.9221773743629456)
('非生物', 0.9185526371002197)
('過金貝', 0.9147799015045166)
不知道是不是我的錯覺,我覺得 Gensim 訓練 Word2Vec 模型感覺效果比較好。
References
- https://github.com/topics/gensim
- https://pypi.org/project/gensim/
- https://fasttext.cc/
- https://github.com/facebookresearch/fastText
写的很详细,赞一个
哈哈,感謝支持!