極簡使用︱Gemsim-FastText 詞向量訓練以及OOV(out-of-word)問題有效解決
glove/word2vec/fasttext目前詞向量比較通用的三種方式,之前三款詞向量的原始訓練過程還是挺繁瑣的,這邊筆者列舉一下再自己使用過程中快速訓練的方式。
其中,word2vec可見:python︱gensim訓練word2vec及相關函式與功能理解
glove可見:極簡使用︱Glove-python詞向量訓練與使用
$ git clone https://github.com/facebookresearch/fastText.git
$ cd fastText
$ pip install .
2 、fasttext訓練
2.1 訓練主函式
from gensim.models import FastText sentences = [["你", "是", "誰"], ["我", "是", "中國人"]] model = FastText(sentences, size=4, window=3, min_count=1, iter=10,min_n = 3 , max_n = 6,word_ngrams = 0) model['你'] # 詞向量獲得的方式 model.wv['你'] # 詞向量獲得的方式
其中FastText主函式為:
class gensim.models.fasttext.FastText(sentences=None, corpus_file=None, sg=0, hs=0, size=100, alpha=0.025, window=5, min_count=5, max_vocab_size=None, word_ngrams=1, sample=0.001, seed=1, workers=3, min_alpha=0.0001, negative=5, ns_exponent=0.75, cbow_mean=1, hashfxn=<built-in function hash>, iter=5, null_word=0, min_n=3, max_n=6, sorted_vocab=1, bucket=2000000, trim_rule=None, batch_words=10000, callbacks=())
幾個引數的含義為:
-
常規引數:
- model: Training architecture. Allowed values:
cbow
,skipgram
(Defaultcbow
) - size: Size of embeddings to be learnt (Default 100)
- alpha: Initial learning rate (Default 0.025)
- window: Context window size (Default 5)
- min_count: Ignore words with number of occurrences below this (Default 5)
- loss: Training objective. Allowed values:
ns
,hs
,softmax
(Defaultns
) - sample: Threshold for downsampling higher-frequency words (Default 0.001)
- negative: Number of negative words to sample, for
ns
(Default 5) - iter: Number of epochs (Default 5)
- sorted_vocab: Sort vocab by descending frequency (Default 1)
- threads: Number of threads to use (Default 12)
- model: Training architecture. Allowed values:
-
fasttext附加引數
- min_n: min length of char ngrams (Default 3)
- max_n: max length of char ngrams (Default 6)
- bucket: number of buckets used for hashing ngrams (Default 2000000)
-
額外引數:
- word_ngrams ({1,0}, optional)
- If 1, uses enriches word vectors with subword(n-grams) information. If 0, this is equivalent to Word2Vec.
- word_ngrams ({1,0}, optional)
2.2 模型的儲存與載入
# 模型儲存與載入
model.save(fname)
model = FastText.load(fname)
那麼既然gensim之中的fasttext,那麼也有這麼一種方式:
fasttext_model.wv.save_word2vec_format('temp/test_fasttext.txt', binary=False)
fasttext_model.wv.save_word2vec_format('temp/test_fasttext.bin', binary=True)
就是將fasttext地詞向量儲存為word2vec的格式,供呼叫:
5 4
是 -0.119938 0.042054504 -0.02282253 -0.10101332
中國人 0.080497965 0.103521846 -0.13045108 -0.01050107
你 -0.0788643 -0.082788676 -0.14035964 0.09101376
我 -0.14597991 0.035916027 -0.120259814 -0.06904249
誰 -0.0021443982 -0.0736454 -0.067576885 -0.025535036
但是,想回來了,如果fasttext儲存為word2vec格式,那麼fasttest能不能重新load進來?
筆者也不清楚,但是筆者沒有看到在fasttext或gensim.models.keyedvectors.FastTextKeyedVectors
,看到load_word2vec_format的函式,所以只能單向輸出:fasttext -> word2vec
如果用FastText.load(fname)
會報錯:
UnpicklingError: invalid load key, '5'.
2.3 線上更新語料庫
# 線上更新訓練 fasttext
from gensim.models import FastText
sentences_1 = [["cat", "say", "meow"], ["dog", "say", "woof"]]
sentences_2 = [["dude", "say", "wazzup!"]]
model = FastText(min_count=1)
model.build_vocab(sentences_1)
model.train(sentences_1, total_examples=model.corpus_count, epochs=model.iter)
model.build_vocab(sentences_2, update=True)
model.train(sentences_2, total_examples=model.corpus_count, epochs=model.iter)
通過build_vocab
來實現
2.4 c++ 版本的fasttext訓練
# 使用c++ 版本的fasttext
from gensim.models.wrappers.fasttext import FastText as FT_wrapper
# Set FastText home to the path to the FastText executable
ft_home = '/home/chinmaya/GSOC/Gensim/fastText/fasttext'
# train the model
model_wrapper = FT_wrapper.train(ft_home, lee_train_file)
print(model_wrapper)
3 fasttext使用
3.1 獲得詞向量
model['你'] # 詞向量獲得的方式
model.wv['你'] # 詞向量獲得的方式
model.wv.word_vec('你')# 詞向量獲得的方式
兩種方式獲得單個單詞的詞向量
還有幾種方式:
sentences = [["你", "是", "誰"], ["我", "是", "中國人"]]
fasttext_model = FastText(sentences, size=4, window=3, min_count=1, iter=10,min_n = 3 , max_n = 6,word_ngrams = 0)
fasttext_model.wv.syn0_vocab # 單詞的向量組 (5, 4)
fasttext_model.wv.vectors_vocab# 單詞的向量組 (5, 4) vectors_vocab == syn0_vocab != vectors
fasttext_model.wv.vectors# 單詞的向量組 (5, 4)
fasttext_model.wv.vectors_ngrams#基於單詞的n-ngram的向量組 (10, 4)
fasttext_model.wv.syn0_ngrams # 基於單詞的n-ngram的向量組 (10, 4)
fasttext_model.wv.num_ngram_vectors # n-ngram數量
fasttext_model.wv.min_n # 最小n-gram
vectors_ngrams與syn0_ngrams 一致,都是n-grams的詞向量矩陣。筆者也不清楚這麼多矩陣具體是指啥。。。
其中fasttext_model.wv.syn0_ngrams
只能返回矩陣,其實他是如下的單詞的fasttext詞向量:
['<中國', '中國人', '國人>', '<中國人', '中國人>', '<中國人>','你',''我,'是','誰']
3.2 詞向量詞典
一種方式就是:fasttext_model.wv.vocab
是以dict形式,還有一種:fasttext_model.wv.index2word
是以list形式
fasttext_model.wv.vocab
fasttext_model.wv.index2word
3.3 與word2vec 相同的求相似性
其中包括:
model.wv.most_similar(positive=['你', '是'], negative=['中國人'])
model.wv.most_similar_cosmul(positive=['你', '是'], negative=['中國人'])
類比關係,其中most_similar_cosmul使用乘法組合來查詢最接近的詞(參考url)
model.wv.doesnt_match("你 真的 是".split()) # 找到不匹配的
找出不適合的詞
model.wv.similarity('你', '是') # 求相似
model.n_similarity(['cat', 'say'], ['dog', 'say']) # 多個詞條求相似
similarity
求兩個詞之間的相似性;n_similarity
為求多個詞之間的相似性
# !pip3 install pyemd
model.wmdistance(['cat', 'say'], ['dog', 'say']) # 求詞條之間的WMD距離
依據詞向量求詞條之間的WMD距離
3.4 求詞附近的相似詞
model.most_similar("滋潤")
model.most_similar(positive=[vector], topn=topn, restrict_vocab=restrict_vocab)
其中,要注意most_similar
是可以直接給入向量,然後來找相似的。這裡官方還有幾種類似的寫法,如下:
model.similar_by_vector('你好')
model.similar_by_word('你好')
其中,有一種增強版的求相似詞的方式:
model.wv.most_similar_cosmul(positive='蘋果手機', negative='手機', topn=10)
官方的解釋為:Positive words still contribute positively towards the similarity, negative words negatively, but with less susceptibility to one large distance dominating the calculation.
3.5 fasttext自帶的OOV功能
fasttext自帶的對於詞典外的詞條進行向量補齊,非常好用。再kaggle的1%方案中就提到fasttext應對OOV的問題,About my 0.9872 single model
原表述:
Fixed misspellings by finding word vector neighborhoods. Fasttext tool can create vectors for out-of-dictionary words which is really nice. I trained my own fasttext vectors on Wikipedia comments corpus and used them to do this. I also used those vectors as embeddings but results were not as good as with regular fasttext vectors.
示例:
model.most_similar("萌萌噠")
[('萌噠', 0.8866026401519775),
('桃江', 0.7472578287124634),
('比榮欣', 0.69571453332901),
('活潑可愛', 0.680438756942749),
('小可愛', 0.6803416013717651),
('可愛', 0.6769561767578125),
('萌', 0.6448146104812622),
('卡通', 0.6299867630004883),
('漂亮可愛', 0.6273207664489746),
('極漂亮', 0.620937705039978)]
關於OOV問題,也可以基於glove等向量來自己構造一套方法
3.5 如何獲得fasttext的n-grams詞向量
fasttext_wrapper.py,20181111補充,來看看fasttext內部如何應對OOV問題:
from gensim.models.utils_any2vec import _save_word2vec_format, _load_word2vec_format, _compute_ngrams, _ft_hash
def compute_ngrams(word, min_n, max_n):
BOW, EOW = ('<', '>') # Used by FastText to attach to all words as prefix and suffix
extended_word = BOW + word + EOW
ngrams = []
for ngram_length in range(min_n, min(len(extended_word), max_n) + 1):
for i in range(0, len(extended_word) - ngram_length + 1):
ngrams.append(extended_word[i:i + ngram_length])
return ngrams
def word_vec(self, word, use_norm=False):
if word in self.vocab:
return super(FastTextKeyedVectors, self).word_vec(word, use_norm)
else:
# from gensim.models.fasttext import compute_ngrams
word_vec = np.zeros(self.vectors_ngrams.shape[1], dtype=np.float32)
ngrams = _compute_ngrams(word, self.min_n, self.max_n)
if use_norm:
ngram_weights = self.vectors_ngrams_norm
else:
ngram_weights = self.vectors_ngrams
ngrams_found = 0
for ngram in ngrams:
ngram_hash = _ft_hash(ngram) % self.bucket
if ngram_hash in self.hash2index:
word_vec += ngram_weights[self.hash2index[ngram_hash]]
ngrams_found += 1
if word_vec.any():
return word_vec / max(1, ngrams_found)
else: # No ngrams of the word are present in self.ngrams
raise KeyError('all ngrams for word %s absent from model' % word)
以上是fasttext如何應對OOV詞的原始計算方式,那麼大致步驟為:
1 找到每個詞的N-grams,_compute_ngrams
函式
2 然後與n-grams詞庫進行匹配
3 匹配到的n-gram向量平均即為最後的輸出值
from gensim.models import FastText
sentences = [["你", "是", "誰"], ["我", "是", "中國人"]]
fasttext_model = FastText(sentences, size=4, window=3, min_count=1, iter=10,min_n = 3 , max_n = 6,word_ngrams = 0)
from gensim.models.utils_any2vec import _save_word2vec_format, _load_word2vec_format, _compute_ngrams, _ft_hash
ngrams = _compute_ngrams('吃了嗎',min_n = 3,max_n = 6)
>>> ['<吃了', '吃了嗎', '了嗎>', '<吃了嗎', '吃了嗎>', '<吃了嗎>']
筆者改編了一下,把fasttext之中的n-grams詞向量可以提取出來。
def FastTextNgramsVector(fasttext_model):
fasttext_word_list = fasttext_model.wv.vocab.keys()
NgramsVector = {}
ngram_weights = fasttext_model.wv.vectors_ngrams # (10, 4)
for word in fasttext_word_list:
ngrams = _compute_ngrams(word,min_n = fasttext_model.wv.min_n,max_n = fasttext_model.wv.max_n)
for ngram in ngrams:
ngram_hash = _ft_hash(ngram) % fasttext_model.wv.bucket
if ngram_hash in fasttext_model.wv.hash2index:
NgramsVector[ngram] = ngram_weights[fasttext_model.wv.hash2index[ngram_hash]]
return NgramsVector
FastTextNgramsVector(fasttext_model)
最終的效果為:
{'<中國': array([ 0.15037228, 0.23413078, -0.09328791, 0.09616131], dtype=float32),
'<中國人': array([ 0.22894476, 0.01658264, 0.09593856, -0.09224218], dtype=float32),
'<中國人>': array([ 0.24443054, 0.12408283, -0.109778 , 0.14463967], dtype=float32),
'<你>': array([-0.10611233, -0.18498571, -0.24031653, 0.08941776], dtype=float32),
'<我>': array([-0.14418595, -0.11722667, -0.00421342, -0.22331873], dtype=float32),
'<是>': array([-0.198387 , -0.02605324, 0.20429775, -0.10319293], dtype=float32),
'<誰>': array([ 0.0370588 , -0.17663571, 0.04465277, 0.09987918], dtype=float32),
'中國人': array([ 0.18819457, 0.19730332, -0.2074779 , -0.23047261], dtype=float32),
'中國人>': array([ 0.09325046, 0.16731283, -0.24085586, 0.12507215], dtype=float32),
'國人>': array([-0.1650848 , 0.18907125, -0.20082659, -0.03944619], dtype=float32)}
可以看到不太相同的是,<中國
會有一個<
符號,要注意。
4 fasttext 與 word2vec的對比
得出的結論:
- 具有n-gram的FastText模型在語法任務上的表現明顯更好,因為句法問題與單詞的形態有關;
- Gensim word2vec和沒有n-gram的fastText模型在語義任務上的效果稍好一些,可能是因為語義問題中的單詞是獨立的單詞而且與它們的char-gram無關;
- 一般來說,隨著語料庫大小的增加,模型的效能似乎越來越接近。但是,這可能是由於模型的維度大小保持恆定在100,而大型語料庫較大維度的模型大小可能會導致更高的效能提升。
- 隨著語料庫大小的增加,所有模型的語義準確性顯著增加。
- 然而,由於n-gram FastText模型的語料庫大小的增加,句法準確度的提高較低(相對和絕對術語)。這可能表明,在較大的語料庫大小的情況下,通過合併形態學資訊獲得的優勢可能不那麼顯著(原始論文中使用的語料庫似乎也表明了這一點)
- 最原始的fastText 由c++寫的,而gensim是由py寫的,執行效能還是c++要快一些
參考資源
相關推薦
極簡使用︱Gemsim-FastText 詞向量訓練以及OOV(out-of-word)問題有效解決
glove/word2vec/fasttext目前詞向量比較通用的三種方式,之前三款詞向量的原始訓練過程還是挺繁瑣的,這邊筆者列舉一下再自己使用過程中快速訓練的方式。 其中,word2vec可見:python︱gensim訓練word2vec及相關函式與功能理解
極簡使用︱Gemsim-FastText 詞向量訓練與使用
glove/word2vec/fasttext目前詞向量比較通用的三種方式,之前三款詞向量的原始訓練過程還是挺繁瑣的,這邊筆者列舉一下再自己使用過程中快速訓練的方式。 其中,word2vec可見:python︱gensim訓練word2vec及相關函式與功能理解 glove可見:極簡使用
用詞袋(bag of word)實現場景識別
前段時間在standford university的計算機視覺:演算法與應用這門課上做了一個小作業——利用詞袋實現場景識別(Scene recognition with bag of words),下面整理如下: 一、詞袋模型 最先是由Jo
極簡使用︱Glove-python詞向量訓練與使用
glove/word2vec/fasttext目前詞向量比較通用的三種方式,其中word2vec來看,在gensim已經可以極快使用(可見:python︱gensim訓練word2vec及相關函式與功能理解) 官方glove教程比較囉嗦,可能還得設定一些引數表,操作不是特別方便。 筆
FastText詞向量表示
論文《Enriching Word Vectors with Subword Information》 介紹 FastText的作者也就是word2vec的作者,所以兩者是一脈相承的。 目前的詞向量模型都是把每一個單詞作為單獨的向量,並沒有考慮詞語的內部結構,那麼F
比賽必備 ︱ 省力搞定三款詞向量訓練 + OOV詞向量問題的可性方案
本篇為資源彙總,一些NLP的比賽在抽取文字特徵的時候會使用非常多的方式。 傳統的有:TFIDF/LDA/LSI等 偏深度的有:word2vec/glove/fasttext等 還有一些預訓練方式:elmo / bert 1 之前的幾款詞向量介紹與訓練
word2vec詞向量訓練及gensim的使用
一、什麼是詞向量 詞向量最初是用one-hot represention表徵的,也就是向量中每一個元素都關聯著詞庫中的一個單詞,指定詞的向量表示為:其在向量中對應的元素設定為1,其他的元素設定為0。採
python中使用Word2Vec多核技術進行新聞詞向量訓練
from sklearn.datasets import fetch_20newsgroups news = fetch_20newsgroups(subset='all') X,y=news.data,news.target from bs4 import Beaut
Windows下使用Word2vec繼續詞向量訓練
2. 下載word2vec,下載地址為:http://word2vec.googlecode.com/svn/trunk/ 將下載的所有檔案放入word2vec資料夾下。 補充: word2vec的原版程式碼是google code上的,也有改寫的其他兩個版本: (1) c++11版本:(jdeng/wo
word2vec詞向量訓練及中文文字相似度計算
本文是講述如何使用word2vec的基礎教程,文章比較基礎,希望對你有所幫助!官網C語言下載地址:http://word2vec.googlecode.com/svn/trunk/官網Python下載地址:http://radimrehurek.com/gensim/mod
python下word2vec詞向量訓練與載入方法
專案中要對短文字進行相似度估計,word2vec是一個很火的工具。本文就word2vec的訓練以及載入進行了總結。word2vec的原理就不描述了,word2vec詞向量工具是由google開發的,輸入為文字文件,輸出為基於這個文字文件的語料庫訓練得到的詞向量模型。通過該模型
詞向量原始碼解析:(6.1)fasttext原始碼解析
fasttext是word2vec的作者mikolov參與的製作的一個工具包,可以用來訓練詞向量和進行文字分類。目前已經引起了廣泛的關注。這個工具包在github上面的地址是 https://github.com/facebookresearch/fastText 這個專案
詞向量原始碼解析:(6.7)fasttext原始碼解析之詞向量1
下面我們看一下怎麼用fasttext生成詞向量。我們執行word-vector-example.sh檔案可以得到考慮了subword的詞向量。首先看一下這個指令碼。首先是下載語料和測試集,下載語料的以後解壓並且用wikifil.pl對語料進行預處理,得到純文字 if [ !
使用Keras和預訓練的詞向量訓練新聞文字分類模型
from __future__ import print_function import os import sys import numpy as np from keras.preprocessing.text import Tokenizer from keras.p
Python極簡教程之六:集合之排序(sorted)
python集合的排序主要使用cmp關鍵字來定義比對函式,以下針對幾個較為典型的型別列舉出對應的方法: 正序排列 普通一維陣列(數值、字串陣列) num = sorted(num) 物件陣列(需要指定欄位排序) cursor = sorted(cursor, cmp=l
詞向量原始碼解析:(1)詞向量(詞表示)簡單介紹
在未來的一段時間內,我會全面細緻的解析包括word2vec, GloVe, hyperwords, context2vec, ngram2vec等一系列詞向量(詞表示)工具包。用合理的向量去表示單詞是自然語言處理(NLP)領域中很經典很基本的一個任務。 一份高質量的詞向
邏輯卷管理器(LVM)以及快照(特殊邏輯卷)的用法
LVM PV VG LV 快照 1.LVM基本介紹2.PV、VG、LV關系詳解(PV/VG/LV的創建、擴展邏輯卷大小、減小(減小操作很少用,僅作學習))3.快照的概念以及基本用法(特殊的邏輯卷)4.總結 LVM基本介紹 LVM:Logical Volume Manager,
支持向量機手把手實戰(進階版本)
HR 程序 不為 strong 間隔 val creat 數組 wid 概要 先前我們實現了基礎版本的 SVM,現在我們來實現進階版本。和上次比,這次優化的地方在於: 啟發式選擇參數 alpha(訓練速度更快)。通過一個外循環來選擇第一個 alpha 值,並且其選擇過程中
tomcat中的字符集問題,測試以及總結(HTTP請求響應)
HTTP伺服器的通常作用可以理解成,接收來自瀏覽器的請求,讀取其中的資訊,並返回http格式的資料 其中,瀏覽器傳送的資料主要以三種形式傳遞,get方式提交的引數,post方式的引數,以及cookie中攜帶的引數三類 而伺服器端,生成http返回資料的形式主要有3種 其中,JSP在本質上與Serv
基於Darknet框架訓練分類器(cifar10資料集)+windows
參考 https://pjreddie.com/darknet/train-cifar/ 1 下載資料集 https://pjreddie.com/media/files/cifar.tgz 在該網址下下載cifar資料集,並解壓在darknet.exe