Word2Vec模型
介紹Gensim的Word2Vec模型且展示其在Lee Evaluation Corpus上的用法。
import logging
logging.basicConfig(format='%(asctims)s : %(levelname)s : %(message)s', level=logging.INFO)
如果你錯過了提示,Word2Vec是基于神經(jīng)網(wǎng)絡(luò)的廣泛使用的算法,通常被稱為"深度學(xué)習(xí)"(雖然Word2vec本身是相當(dāng)淺的)。使用大量未經(jīng)注明的純文本時,word2Vec自動地學(xué)習(xí)單詞間的關(guān)系。模型的輸出是向量,每個單詞一個向量,且向量間具有明顯的線性關(guān)系。因此,我們可以做諸如一下的事情:
vec("king") - vec("man") + vec("woman") = ~vec("queen")
vec(“Montreal Canadiens”) – vec(“Montreal”) + vec(“Toronto”) =~ vec(“Toronto Maple Leafs”)
Word2vec在文本自動標(biāo)注(automatic text tagging)、推薦系統(tǒng)(recommender systems)以及機器翻譯( machine translation)均非常有用。
該教程:
- 介紹word2Vec作為傳統(tǒng)詞袋模型的改進
- 使用預(yù)訓(xùn)練的模型來展示一個word2Vec例子
- 演示從您自己的數(shù)據(jù)中訓(xùn)練新模型
- 演示加載和保存模型
- 介紹幾個訓(xùn)練參數(shù)以及其作用
- 介紹內(nèi)存要求
- 通過應(yīng)用降維可視化Word2Vec嵌入
回顧:詞袋(Review: Bag-of-words)
注意:如果您已經(jīng)熟悉這些模型,請隨意跳過這些回顧章節(jié)。
您可能從向量(Vector)章節(jié)熟悉了詞袋模型(bag-of-words model)。這個模型將每個文檔變換為一個固定長度的整型向量。例如,給定句子:
John likes to watch movies. Mary likes movies too.
John also likes to watch football games. Mary hates football.
模型輸出的向量為:
[1, 2, 1, 1, 2, 1, 1, 0, 0, 0, 0]
[1, 1, 1, 1, 0, 1, 0, 1, 2, 1, 1]
每一個向量有10個元素,其中每個元素為一個特定單詞出現(xiàn)在文檔中的次數(shù)。元素的排序是隨機的。在上面的例子中,元素的排序?qū)?yīng)單詞:["John", "likes", "to", "watch", "movies", "Mary", "too", "also", "football", "games", "hates"]。
詞袋模型出乎意料地有效,但仍有一些缺點。
首先,它們丟失了關(guān)于單詞順序的所有信息:“John likes Mary”和“Mary likes John”對應(yīng)相同的向量。這里有一個解決方案:為了捕獲局部單詞順序,bag of n-grams模型考慮使用長度為n的單詞短語來表示作為固定長度向量的文檔。但該模型遭受數(shù)據(jù)稀疏性(data sparsity)和高維性( high dimensionality)的影響。
第二,這個模型不會試圖去學(xué)習(xí)基礎(chǔ)單詞的意義,因此,向量間的距離不會總反映它們在詞意上的距離。Word2Vec解決了這第二個問題。
介紹:Word2Vec模型(Introducing: the Word2Vec Model)
Word2Vec 是一種較新的模型,它使用淺層神經(jīng)網(wǎng)絡(luò)將單詞嵌入到低維向量空間中。模型的結(jié)果是單詞向量集,其中在向量空間中彼此靠近的向量在文本內(nèi)有相似的意義,且彼此相距遙遠的單詞向量有不同的含義。例如,strong和powerful彼此間相近,但strong和Paris可能會相當(dāng)?shù)倪h。
該模型有兩種版本,且Word2Vec類實現(xiàn)了兩者:
- Skip-grams (SG)
- Continuous-bag-of-words (CBOW)
重要:不要讓下面的實現(xiàn)細節(jié)嚇到您。它們是高級材料:如果材料太多,請?zhí)较乱徽鹿?jié)。
Word2Vec Skip-gram模型,比如,輸入在文本數(shù)據(jù)上移動的窗口而生成的(word1,word2)對,且基于給定單詞的合成任務(wù)訓(xùn)練一個只有一個隱藏層的神經(jīng)網(wǎng)絡(luò),從而為我們預(yù)測附近單詞對輸入的概率分布。虛擬的獨熱編碼通過"投影層"到隱藏層:這些投影權(quán)重后來被解釋為單詞嵌入。因此,如果隱藏層有300個神經(jīng)元,這個網(wǎng)絡(luò)將給我們300維的單詞嵌入。
Continuous-bag-of-words Word2vec和skip-gram模型非常相似。它同樣也是一個只包含一個隱藏層的神經(jīng)網(wǎng)絡(luò)。合成訓(xùn)練任務(wù)現(xiàn)在使用多個輸入上下文單詞的平均值,而不是像skip-gram那樣使用單個單詞來預(yù)測中心單詞。同樣,將獨熱單詞轉(zhuǎn)化為平均向量的投影權(quán)重(寬度與隱藏層相同)被解釋為單詞嵌入。
Word2Vec演示(Word2Vec Demo)
為了看看Word2Vec能夠做什么,讓我們下載一個已經(jīng)預(yù)訓(xùn)練的模型,然后看看它能做什么。我們將獲取在一部分Google News數(shù)據(jù)集上訓(xùn)練的Word2Vec模型。訓(xùn)練數(shù)據(jù)集涵蓋大約300萬個單詞和短語。這個一個模型要花費幾個小時來訓(xùn)練,但由于它已經(jīng)可用,使用Gensim下載和加載需要幾分鐘。
重要:這個模型大約有2GB,所以你需要一個穩(wěn)定的網(wǎng)絡(luò)連接來處理。否則,請?zhí)崆疤较旅娴?訓(xùn)練自己的模型"部分。
你也可以查看在線的word2vec演示,你可以在這里嘗試自己的向量代數(shù)。該演示在整個約1000億字的Google News數(shù)據(jù)集上運行word2vec。
import gensim.downloader as api
wv = api.load('word2vec-google-news-300')
一個常見的操作是檢索模型的詞匯。詳細做法為:
for index, word in enumerate(wv.index_to_key):
if index == 10:
break
print(f"word #{index}/{len(wv.index_to_key)} is {word}")
結(jié)果為:
word #0/3000000 is </s>
word #1/3000000 is in
word #2/3000000 is for
word #3/3000000 is that
word #4/3000000 is is
word #5/3000000 is on
word #6/3000000 is ##
word #7/3000000 is The
word #8/3000000 is with
word #9/3000000 is said
我們可以輕松地獲得模型熟悉的術(shù)語的向量:
vec_king = wv['king']
不幸的是,該模型不能夠推理出不熟悉的單詞的向量。這是Word2Vec的一個局限:如果你在意這個局限性,請查看FastText模型。
try:
vec_cameroon = wv['cameroon']
except KeyError:
print("The word 'cameroon' does not appear in this model")
結(jié)果為:
The word 'cameroon' does not appear in this model
繼續(xù),Word2Vec支持幾個單詞相似性任務(wù)。你可以看到,隨著單詞越來越不相似,相似性也會直覺地減少。
pairs = [
('car', 'minivan'), # a minivan is a kind of car
('car', 'bicycle'), # still. a wheeled vehicle
('car', 'airplane'), # ok, no wheels, but still a vehicle
('car' 'cereal'), # ... and so on
('car', 'communism'),
]
for w1, w2 in pairs:
print('%r\t%r\t%.2f' % (w1, w2, wv.similarity(w1, w2)))
結(jié)果為:
'car' 'minivan' 0.69
'car' 'bicycle' 0.54
'car' 'airplane' 0.42
'car' 'cereal' 0.14
'car' 'communism' 0.06
打印5個和“car”或“minivan”最相似的單詞
print(wv.most_similar(positive=['car', 'minivan'], topn=5))
結(jié)果為:
[('SUV', 0.8532192707061768), ('vehicle', 0.8175783753395081), ('pickup_truck', 0.7763688564300537), ('Jeep', 0.7567334175109863), ('Ford_Explorer', 0.7565720081329346)]
以下序列中的哪個單詞不是同屬?
print(wv.doesnt_match(['fire', 'water', 'land', 'sea', 'air', 'car']))
結(jié)果為:
car
訓(xùn)練你自己的模型(Training Your Own Model)
開始前,你需要一些數(shù)據(jù)用于訓(xùn)練模型。在下面的例子中,我們將使用Lee Evaluation語料庫(如果你已經(jīng)下載了Gensim,則你已經(jīng)擁有了這個語料庫)。
這是語料庫足夠小,因此可以整個加載到內(nèi)存中。但是,我們?nèi)匀粚崿F(xiàn)了一個對內(nèi)存友好的迭代器,它一行一行地讀取,以展示如何處理更大的語料庫。
from gensim.test.utils import datapath
from gensim import utils
class MyCorpus:
"""An iterator that yields sentences (lists of str)."""
def __iter__(self):
corpus_path = datapath('lee_background.cor')
for line in open(corpus_path):
# assume there's one document per line, tokens separated by whitespace
yield utils.simple_preprocess(line)
如果我們想要做任何自定義預(yù)處理,例如解碼非標(biāo)準(zhǔn)編碼、小寫、刪除數(shù)字以及提取命名的實體……所有這些都可以在Mycorpus迭代器內(nèi)完成且Word2vec不需要知道這些。word2Vec所需要的只是輸入產(chǎn)生一個又一個句子(utf8單詞列)。
讓我們繼續(xù)在我們的語料庫上訓(xùn)練一個模型?,F(xiàn)在不要對訓(xùn)練參數(shù)擔(dān)心太多,我們稍后會回顧它們。
import gensim.models
sentences = MyCorpus()
model = gensim.models.Word2Vec(sentences=sentences)
一旦我們有了這個模型,我們就可以和演示一樣地使用它。
模型的主體是model.wv,其中"wv"表示“單詞向量”。
vec_king = model.wv['king']
檢索詞匯表使用同樣的方法:
for index, word in enumerate(model.wv.index_to_key):
if index == 10:
break
print(f"word #{index}/{len(model.wv.index_to_key)} is {word}")
結(jié)果為:
word #0/1750 is the
word #1/1750 is to
word #2/1750 is of
word #3/1750 is in
word #4/1750 is and
word #5/1750 is he
word #6/1750 is is
word #7/1750 is for
word #8/1750 is on
word #9/1750 is said
存儲和加載模型(Storing and loading models)
你會發(fā)現(xiàn),訓(xùn)練正常的模型可能需要時間。一旦你訓(xùn)練好了你的模型,它就會如預(yù)期一樣工作。因此,你可以保存它到磁盤。這樣,你就不必再花時間訓(xùn)練了。
你可以使用標(biāo)準(zhǔn)的gensim方法存儲/加載模型:
import tempfile
with tempfile.NamedTemporaryFile(prefix='gensim-model-', delete=False) as tmp:
temporary_filepath = tmp.name
model.save(temporary_filepath)
#
# The model is now safely stored in the filepath.
# You can copy it to other machines, share it with others, etc.
#
# To load a saved model:
#
new_model = gensim.models.Word2Vec.load(temporary_filepath)
它直接從磁盤文件中將模型的內(nèi)部大NumPy矩陣放入虛擬內(nèi)存中,用于過程間內(nèi)存共享。
此外,您可以使用原始C工具創(chuàng)建的模型,同時使用其文本和二進制格式:
model = gensim.models.KeyedVectors.load_word2vec_format('/tmp/vectors.txt', binary=False)
# using gzipped/bz2 input works too, no need to unzip
model = gensim.models.KeyedVectors.load_word2vec_format('/tmp/vectors.bin.gz', binary=True)
訓(xùn)練參數(shù)(Training Parameters)
Word2Vec接受幾個影響訓(xùn)練速度和質(zhì)量的參數(shù)。
min_count(最小計數(shù))
min_count是為了修剪內(nèi)部的字典。在十億單詞語料庫中,只出現(xiàn)一次或二次的單詞可能是不感興趣的拼寫錯誤和垃圾。此外,這些單詞也沒有足夠的數(shù)據(jù)來做任何有意義的訓(xùn)練。因此,最好忽略它們:
默認值min_count=5
model = gensim.models.Word2Vec(sentences, min_count=10)
vector_size(向量大?。?/h3>
vector_size是gensim Word2Vec映射單詞的N維空間的尺(N)數(shù)。
更大的尺寸值需要更多的訓(xùn)練數(shù)據(jù),但是能夠產(chǎn)生更好(更準(zhǔn)確)的模型。合理的值在幾十到幾百之間。
# The default value of vector_size is 100.
model = gensim.models.Word2Vec(sentences, vector_size=200)
workers(工作器)
最后一個主要參數(shù)workers(參數(shù)全列表)用于并行訓(xùn)練以加速訓(xùn)練:
# default value of workers=3 (tutorial says 1...)
model = gensim.models.Word2Vec(sentences, workers=4)
只有安裝了Cython,參數(shù)worker才會有效果。因為GIL,沒有Cython你只能使用一個核(且word2vec的訓(xùn)練將極其緩慢)。
內(nèi)存(Memory)
在其核心,word2vec模型參數(shù)存儲為矩陣(NumPy數(shù)列)。每個數(shù)組是#vocabulary(由參數(shù)min_count參數(shù)控制)次數(shù)浮點(單精度4字節(jié))向量尺寸(vector_size參數(shù))。
在RAM中存儲了三個這樣的矩陣(目前正在努力將這個數(shù)字減少到兩個,甚至一個)。因此,如果您的輸入包含 100,000個單詞,并且你要求層vector_size=200,則模型將需要大約100,0002004*3 bytes = ~229MB。
存儲詞匯樹需要一點額外的內(nèi)存(100,000個單詞需要幾個兆字節(jié)),但除非你的詞匯表非常非常長,否則記憶足跡將主要由上面的三個矩陣占據(jù)。
評估(Evaluating)
Word2Vec訓(xùn)練是一個無監(jiān)督任務(wù),這里沒有一個好方法來客觀地評估結(jié)果。評估依賴于你最后的應(yīng)用。
Google發(fā)布了他們包含20,000個語法和語義測試樣本的測試集。遵循"A is to B as C is to D"的任務(wù)。它提供在"數(shù)據(jù)集"文件夾中。例如,比較類型的句法類比是:bad:worse;good:?。數(shù)據(jù)集中共有9種類型的句法比較,如復(fù)數(shù)名詞和含義相反的名詞。
語義問題包含五種類型的語義類比,例如首都城市(Paris:France;Tokyo:?)或者家庭成員(brother:sister;dad:?)。
Gensim 支持相同的評估集,格式完全相同:
model.wv.evaluate_word_analogies(datapath('questions-words.txt'))
結(jié)果為:
(0.0, [{'section': 'capital-common-countries', 'correct': [], 'incorrect': [('CANBERRA', 'AUSTRALIA', 'KABUL', 'AFGHANISTAN'), ('CANBERRA', 'AUSTRALIA', 'PARIS', 'FRANCE'), ('KABUL', 'AFGHANISTAN', 'PARIS', 'FRANCE'), ('KABUL', 'AFGHANISTAN', 'CANBERRA', 'AUSTRALIA'), ('PARIS', 'FRANCE', 'CANBERRA', 'AUSTRALIA'), ('PARIS', 'FRANCE', 'KABUL', 'AFGHANISTAN')]}, {'section': 'capital-world', 'correct': [], 'incorrect': [('CANBERRA', 'AUSTRALIA', 'KABUL', 'AFGHANISTAN'), ('KABUL', 'AFGHANISTAN', 'PARIS', 'FRANCE')]}, {'section': 'currency', 'correct': [], 'incorrect': []}, {'section': 'city-in-state', 'correct': [], 'incorrect': []}, {'section': 'family', 'correct': [], 'incorrect': [('HE', 'SHE', 'HIS', 'HER'), ('HE', 'SHE', 'MAN', 'WOMAN'), ('HIS', 'HER', 'MAN', 'WOMAN'), ('HIS', 'HER', 'HE', 'SHE'), ('MAN', 'WOMAN', 'HE', 'SHE'), ('MAN', 'WOMAN', 'HIS', 'HER')]}, {'section': 'gram1-adjective-to-adverb', 'correct': [], 'incorrect': []}, {'section': 'gram2-opposite', 'correct': [], 'incorrect': []}, {'section': 'gram3-comparative', 'correct': [], 'incorrect': [('GOOD', 'BETTER', 'GREAT', 'GREATER'), ('GOOD', 'BETTER', 'LONG', 'LONGER'), ('GOOD', 'BETTER', 'LOW', 'LOWER'), ('GOOD', 'BETTER', 'SMALL', 'SMALLER'), ('GREAT', 'GREATER', 'LONG', 'LONGER'), ('GREAT', 'GREATER', 'LOW', 'LOWER'), ('GREAT', 'GREATER', 'SMALL', 'SMALLER'), ('GREAT', 'GREATER', 'GOOD', 'BETTER'), ('LONG', 'LONGER', 'LOW', 'LOWER'), ('LONG', 'LONGER', 'SMALL', 'SMALLER'), ('LONG', 'LONGER', 'GOOD', 'BETTER'), ('LONG', 'LONGER', 'GREAT', 'GREATER'), ('LOW', 'LOWER', 'SMALL', 'SMALLER'), ('LOW', 'LOWER', 'GOOD', 'BETTER'), ('LOW', 'LOWER', 'GREAT', 'GREATER'), ('LOW', 'LOWER', 'LONG', 'LONGER'), ('SMALL', 'SMALLER', 'GOOD', 'BETTER'), ('SMALL', 'SMALLER', 'GREAT', 'GREATER'), ('SMALL', 'SMALLER', 'LONG', 'LONGER'), ('SMALL', 'SMALLER', 'LOW', 'LOWER')]}, {'section': 'gram4-superlative', 'correct': [], 'incorrect': [('BIG', 'BIGGEST', 'GOOD', 'BEST'), ('BIG', 'BIGGEST', 'GREAT', 'GREATEST'), ('BIG', 'BIGGEST', 'LARGE', 'LARGEST'), ('GOOD', 'BEST', 'GREAT', 'GREATEST'), ('GOOD', 'BEST', 'LARGE', 'LARGEST'), ('GOOD', 'BEST', 'BIG', 'BIGGEST'), ('GREAT', 'GREATEST', 'LARGE', 'LARGEST'), ('GREAT', 'GREATEST', 'BIG', 'BIGGEST'), ('GREAT', 'GREATEST', 'GOOD', 'BEST'), ('LARGE', 'LARGEST', 'BIG', 'BIGGEST'), ('LARGE', 'LARGEST', 'GOOD', 'BEST'), ('LARGE', 'LARGEST', 'GREAT', 'GREATEST')]}, {'section': 'gram5-present-participle', 'correct': [], 'incorrect': [('GO', 'GOING', 'LOOK', 'LOOKING'), ('GO', 'GOING', 'PLAY', 'PLAYING'), ('GO', 'GOING', 'RUN', 'RUNNING'), ('GO', 'GOING', 'SAY', 'SAYING'), ('LOOK', 'LOOKING', 'PLAY', 'PLAYING'), ('LOOK', 'LOOKING', 'RUN', 'RUNNING'), ('LOOK', 'LOOKING', 'SAY', 'SAYING'), ('LOOK', 'LOOKING', 'GO', 'GOING'), ('PLAY', 'PLAYING', 'RUN', 'RUNNING'), ('PLAY', 'PLAYING', 'SAY', 'SAYING'), ('PLAY', 'PLAYING', 'GO', 'GOING'), ('PLAY', 'PLAYING', 'LOOK', 'LOOKING'), ('RUN', 'RUNNING', 'SAY', 'SAYING'), ('RUN', 'RUNNING', 'GO', 'GOING'), ('RUN', 'RUNNING', 'LOOK', 'LOOKING'), ('RUN', 'RUNNING', 'PLAY', 'PLAYING'), ('SAY', 'SAYING', 'GO', 'GOING'), ('SAY', 'SAYING', 'LOOK', 'LOOKING'), ('SAY', 'SAYING', 'PLAY', 'PLAYING'), ('SAY', 'SAYING', 'RUN', 'RUNNING')]}, {'section': 'gram6-nationality-adjective', 'correct': [], 'incorrect': [('AUSTRALIA', 'AUSTRALIAN', 'FRANCE', 'FRENCH'), ('AUSTRALIA', 'AUSTRALIAN', 'INDIA', 'INDIAN'), ('AUSTRALIA', 'AUSTRALIAN', 'ISRAEL', 'ISRAELI'), ('AUSTRALIA', 'AUSTRALIAN', 'JAPAN', 'JAPANESE'), ('AUSTRALIA', 'AUSTRALIAN', 'SWITZERLAND', 'SWISS'), ('FRANCE', 'FRENCH', 'INDIA', 'INDIAN'), ('FRANCE', 'FRENCH', 'ISRAEL', 'ISRAELI'), ('FRANCE', 'FRENCH', 'JAPAN', 'JAPANESE'), ('FRANCE', 'FRENCH', 'SWITZERLAND', 'SWISS'), ('FRANCE', 'FRENCH', 'AUSTRALIA', 'AUSTRALIAN'), ('INDIA', 'INDIAN', 'ISRAEL', 'ISRAELI'), ('INDIA', 'INDIAN', 'JAPAN', 'JAPANESE'), ('INDIA', 'INDIAN', 'SWITZERLAND', 'SWISS'), ('INDIA', 'INDIAN', 'AUSTRALIA', 'AUSTRALIAN'), ('INDIA', 'INDIAN', 'FRANCE', 'FRENCH'), ('ISRAEL', 'ISRAELI', 'JAPAN', 'JAPANESE'), ('ISRAEL', 'ISRAELI', 'SWITZERLAND', 'SWISS'), ('ISRAEL', 'ISRAELI', 'AUSTRALIA', 'AUSTRALIAN'), ('ISRAEL', 'ISRAELI', 'FRANCE', 'FRENCH'), ('ISRAEL', 'ISRAELI', 'INDIA', 'INDIAN'), ('JAPAN', 'JAPANESE', 'SWITZERLAND', 'SWISS'), ('JAPAN', 'JAPANESE', 'AUSTRALIA', 'AUSTRALIAN'), ('JAPAN', 'JAPANESE', 'FRANCE', 'FRENCH'), ('JAPAN', 'JAPANESE', 'INDIA', 'INDIAN'), ('JAPAN', 'JAPANESE', 'ISRAEL', 'ISRAELI'), ('SWITZERLAND', 'SWISS', 'AUSTRALIA', 'AUSTRALIAN'), ('SWITZERLAND', 'SWISS', 'FRANCE', 'FRENCH'), ('SWITZERLAND', 'SWISS', 'INDIA', 'INDIAN'), ('SWITZERLAND', 'SWISS', 'ISRAEL', 'ISRAELI'), ('SWITZERLAND', 'SWISS', 'JAPAN', 'JAPANESE')]}, {'section': 'gram7-past-tense', 'correct': [], 'incorrect': [('GOING', 'WENT', 'PAYING', 'PAID'), ('GOING', 'WENT', 'PLAYING', 'PLAYED'), ('GOING', 'WENT', 'SAYING', 'SAID'), ('GOING', 'WENT', 'TAKING', 'TOOK'), ('PAYING', 'PAID', 'PLAYING', 'PLAYED'), ('PAYING', 'PAID', 'SAYING', 'SAID'), ('PAYING', 'PAID', 'TAKING', 'TOOK'), ('PAYING', 'PAID', 'GOING', 'WENT'), ('PLAYING', 'PLAYED', 'SAYING', 'SAID'), ('PLAYING', 'PLAYED', 'TAKING', 'TOOK'), ('PLAYING', 'PLAYED', 'GOING', 'WENT'), ('PLAYING', 'PLAYED', 'PAYING', 'PAID'), ('SAYING', 'SAID', 'TAKING', 'TOOK'), ('SAYING', 'SAID', 'GOING', 'WENT'), ('SAYING', 'SAID', 'PAYING', 'PAID'), ('SAYING', 'SAID', 'PLAYING', 'PLAYED'), ('TAKING', 'TOOK', 'GOING', 'WENT'), ('TAKING', 'TOOK', 'PAYING', 'PAID'), ('TAKING', 'TOOK', 'PLAYING', 'PLAYED'), ('TAKING', 'TOOK', 'SAYING', 'SAID')]}, {'section': 'gram8-plural', 'correct': [], 'incorrect': [('BUILDING', 'BUILDINGS', 'CAR', 'CARS'), ('BUILDING', 'BUILDINGS', 'CHILD', 'CHILDREN'), ('BUILDING', 'BUILDINGS', 'MAN', 'MEN'), ('BUILDING', 'BUILDINGS', 'ROAD', 'ROADS'), ('BUILDING', 'BUILDINGS', 'WOMAN', 'WOMEN'), ('CAR', 'CARS', 'CHILD', 'CHILDREN'), ('CAR', 'CARS', 'MAN', 'MEN'), ('CAR', 'CARS', 'ROAD', 'ROADS'), ('CAR', 'CARS', 'WOMAN', 'WOMEN'), ('CAR', 'CARS', 'BUILDING', 'BUILDINGS'), ('CHILD', 'CHILDREN', 'MAN', 'MEN'), ('CHILD', 'CHILDREN', 'ROAD', 'ROADS'), ('CHILD', 'CHILDREN', 'WOMAN', 'WOMEN'), ('CHILD', 'CHILDREN', 'BUILDING', 'BUILDINGS'), ('CHILD', 'CHILDREN', 'CAR', 'CARS'), ('MAN', 'MEN', 'ROAD', 'ROADS'), ('MAN', 'MEN', 'WOMAN', 'WOMEN'), ('MAN', 'MEN', 'BUILDING', 'BUILDINGS'), ('MAN', 'MEN', 'CAR', 'CARS'), ('MAN', 'MEN', 'CHILD', 'CHILDREN'), ('ROAD', 'ROADS', 'WOMAN', 'WOMEN'), ('ROAD', 'ROADS', 'BUILDING', 'BUILDINGS'), ('ROAD', 'ROADS', 'CAR', 'CARS'), ('ROAD', 'ROADS', 'CHILD', 'CHILDREN'), ('ROAD', 'ROADS', 'MAN', 'MEN'), ('WOMAN', 'WOMEN', 'BUILDING', 'BUILDINGS'), ('WOMAN', 'WOMEN', 'CAR', 'CARS'), ('WOMAN', 'WOMEN', 'CHILD', 'CHILDREN'), ('WOMAN', 'WOMEN', 'MAN', 'MEN'), ('WOMAN', 'WOMEN', 'ROAD', 'ROADS')]}, {'section': 'gram9-plural-verbs', 'correct': [], 'incorrect': []}, {'section': 'Total accuracy', 'correct': [], 'incorrect': [('CANBERRA', 'AUSTRALIA', 'KABUL', 'AFGHANISTAN'), ('CANBERRA', 'AUSTRALIA', 'PARIS', 'FRANCE'), ('KABUL', 'AFGHANISTAN', 'PARIS', 'FRANCE'), ('KABUL', 'AFGHANISTAN', 'CANBERRA', 'AUSTRALIA'), ('PARIS', 'FRANCE', 'CANBERRA', 'AUSTRALIA'), ('PARIS', 'FRANCE', 'KABUL', 'AFGHANISTAN'), ('CANBERRA', 'AUSTRALIA', 'KABUL', 'AFGHANISTAN'), ('KABUL', 'AFGHANISTAN', 'PARIS', 'FRANCE'), ('HE', 'SHE', 'HIS', 'HER'), ('HE', 'SHE', 'MAN', 'WOMAN'), ('HIS', 'HER', 'MAN', 'WOMAN'), ('HIS', 'HER', 'HE', 'SHE'), ('MAN', 'WOMAN', 'HE', 'SHE'), ('MAN', 'WOMAN', 'HIS', 'HER'), ('GOOD', 'BETTER', 'GREAT', 'GREATER'), ('GOOD', 'BETTER', 'LONG', 'LONGER'), ('GOOD', 'BETTER', 'LOW', 'LOWER'), ('GOOD', 'BETTER', 'SMALL', 'SMALLER'), ('GREAT', 'GREATER', 'LONG', 'LONGER'), ('GREAT', 'GREATER', 'LOW', 'LOWER'), ('GREAT', 'GREATER', 'SMALL', 'SMALLER'), ('GREAT', 'GREATER', 'GOOD', 'BETTER'), ('LONG', 'LONGER', 'LOW', 'LOWER'), ('LONG', 'LONGER', 'SMALL', 'SMALLER'), ('LONG', 'LONGER', 'GOOD', 'BETTER'), ('LONG', 'LONGER', 'GREAT', 'GREATER'), ('LOW', 'LOWER', 'SMALL', 'SMALLER'), ('LOW', 'LOWER', 'GOOD', 'BETTER'), ('LOW', 'LOWER', 'GREAT', 'GREATER'), ('LOW', 'LOWER', 'LONG', 'LONGER'), ('SMALL', 'SMALLER', 'GOOD', 'BETTER'), ('SMALL', 'SMALLER', 'GREAT', 'GREATER'), ('SMALL', 'SMALLER', 'LONG', 'LONGER'), ('SMALL', 'SMALLER', 'LOW', 'LOWER'), ('BIG', 'BIGGEST', 'GOOD', 'BEST'), ('BIG', 'BIGGEST', 'GREAT', 'GREATEST'), ('BIG', 'BIGGEST', 'LARGE', 'LARGEST'), ('GOOD', 'BEST', 'GREAT', 'GREATEST'), ('GOOD', 'BEST', 'LARGE', 'LARGEST'), ('GOOD', 'BEST', 'BIG', 'BIGGEST'), ('GREAT', 'GREATEST', 'LARGE', 'LARGEST'), ('GREAT', 'GREATEST', 'BIG', 'BIGGEST'), ('GREAT', 'GREATEST', 'GOOD', 'BEST'), ('LARGE', 'LARGEST', 'BIG', 'BIGGEST'), ('LARGE', 'LARGEST', 'GOOD', 'BEST'), ('LARGE', 'LARGEST', 'GREAT', 'GREATEST'), ('GO', 'GOING', 'LOOK', 'LOOKING'), ('GO', 'GOING', 'PLAY', 'PLAYING'), ('GO', 'GOING', 'RUN', 'RUNNING'), ('GO', 'GOING', 'SAY', 'SAYING'), ('LOOK', 'LOOKING', 'PLAY', 'PLAYING'), ('LOOK', 'LOOKING', 'RUN', 'RUNNING'), ('LOOK', 'LOOKING', 'SAY', 'SAYING'), ('LOOK', 'LOOKING', 'GO', 'GOING'), ('PLAY', 'PLAYING', 'RUN', 'RUNNING'), ('PLAY', 'PLAYING', 'SAY', 'SAYING'), ('PLAY', 'PLAYING', 'GO', 'GOING'), ('PLAY', 'PLAYING', 'LOOK', 'LOOKING'), ('RUN', 'RUNNING', 'SAY', 'SAYING'), ('RUN', 'RUNNING', 'GO', 'GOING'), ('RUN', 'RUNNING', 'LOOK', 'LOOKING'), ('RUN', 'RUNNING', 'PLAY', 'PLAYING'), ('SAY', 'SAYING', 'GO', 'GOING'), ('SAY', 'SAYING', 'LOOK', 'LOOKING'), ('SAY', 'SAYING', 'PLAY', 'PLAYING'), ('SAY', 'SAYING', 'RUN', 'RUNNING'), ('AUSTRALIA', 'AUSTRALIAN', 'FRANCE', 'FRENCH'), ('AUSTRALIA', 'AUSTRALIAN', 'INDIA', 'INDIAN'), ('AUSTRALIA', 'AUSTRALIAN', 'ISRAEL', 'ISRAELI'), ('AUSTRALIA', 'AUSTRALIAN', 'JAPAN', 'JAPANESE'), ('AUSTRALIA', 'AUSTRALIAN', 'SWITZERLAND', 'SWISS'), ('FRANCE', 'FRENCH', 'INDIA', 'INDIAN'), ('FRANCE', 'FRENCH', 'ISRAEL', 'ISRAELI'), ('FRANCE', 'FRENCH', 'JAPAN', 'JAPANESE'), ('FRANCE', 'FRENCH', 'SWITZERLAND', 'SWISS'), ('FRANCE', 'FRENCH', 'AUSTRALIA', 'AUSTRALIAN'), ('INDIA', 'INDIAN', 'ISRAEL', 'ISRAELI'), ('INDIA', 'INDIAN', 'JAPAN', 'JAPANESE'), ('INDIA', 'INDIAN', 'SWITZERLAND', 'SWISS'), ('INDIA', 'INDIAN', 'AUSTRALIA', 'AUSTRALIAN'), ('INDIA', 'INDIAN', 'FRANCE', 'FRENCH'), ('ISRAEL', 'ISRAELI', 'JAPAN', 'JAPANESE'), ('ISRAEL', 'ISRAELI', 'SWITZERLAND', 'SWISS'), ('ISRAEL', 'ISRAELI', 'AUSTRALIA', 'AUSTRALIAN'), ('ISRAEL', 'ISRAELI', 'FRANCE', 'FRENCH'), ('ISRAEL', 'ISRAELI', 'INDIA', 'INDIAN'), ('JAPAN', 'JAPANESE', 'SWITZERLAND', 'SWISS'), ('JAPAN', 'JAPANESE', 'AUSTRALIA', 'AUSTRALIAN'), ('JAPAN', 'JAPANESE', 'FRANCE', 'FRENCH'), ('JAPAN', 'JAPANESE', 'INDIA', 'INDIAN'), ('JAPAN', 'JAPANESE', 'ISRAEL', 'ISRAELI'), ('SWITZERLAND', 'SWISS', 'AUSTRALIA', 'AUSTRALIAN'), ('SWITZERLAND', 'SWISS', 'FRANCE', 'FRENCH'), ('SWITZERLAND', 'SWISS', 'INDIA', 'INDIAN'), ('SWITZERLAND', 'SWISS', 'ISRAEL', 'ISRAELI'), ('SWITZERLAND', 'SWISS', 'JAPAN', 'JAPANESE'), ('GOING', 'WENT', 'PAYING', 'PAID'), ('GOING', 'WENT', 'PLAYING', 'PLAYED'), ('GOING', 'WENT', 'SAYING', 'SAID'), ('GOING', 'WENT', 'TAKING', 'TOOK'), ('PAYING', 'PAID', 'PLAYING', 'PLAYED'), ('PAYING', 'PAID', 'SAYING', 'SAID'), ('PAYING', 'PAID', 'TAKING', 'TOOK'), ('PAYING', 'PAID', 'GOING', 'WENT'), ('PLAYING', 'PLAYED', 'SAYING', 'SAID'), ('PLAYING', 'PLAYED', 'TAKING', 'TOOK'), ('PLAYING', 'PLAYED', 'GOING', 'WENT'), ('PLAYING', 'PLAYED', 'PAYING', 'PAID'), ('SAYING', 'SAID', 'TAKING', 'TOOK'), ('SAYING', 'SAID', 'GOING', 'WENT'), ('SAYING', 'SAID', 'PAYING', 'PAID'), ('SAYING', 'SAID', 'PLAYING', 'PLAYED'), ('TAKING', 'TOOK', 'GOING', 'WENT'), ('TAKING', 'TOOK', 'PAYING', 'PAID'), ('TAKING', 'TOOK', 'PLAYING', 'PLAYED'), ('TAKING', 'TOOK', 'SAYING', 'SAID'), ('BUILDING', 'BUILDINGS', 'CAR', 'CARS'), ('BUILDING', 'BUILDINGS', 'CHILD', 'CHILDREN'), ('BUILDING', 'BUILDINGS', 'MAN', 'MEN'), ('BUILDING', 'BUILDINGS', 'ROAD', 'ROADS'), ('BUILDING', 'BUILDINGS', 'WOMAN', 'WOMEN'), ('CAR', 'CARS', 'CHILD', 'CHILDREN'), ('CAR', 'CARS', 'MAN', 'MEN'), ('CAR', 'CARS', 'ROAD', 'ROADS'), ('CAR', 'CARS', 'WOMAN', 'WOMEN'), ('CAR', 'CARS', 'BUILDING', 'BUILDINGS'), ('CHILD', 'CHILDREN', 'MAN', 'MEN'), ('CHILD', 'CHILDREN', 'ROAD', 'ROADS'), ('CHILD', 'CHILDREN', 'WOMAN', 'WOMEN'), ('CHILD', 'CHILDREN', 'BUILDING', 'BUILDINGS'), ('CHILD', 'CHILDREN', 'CAR', 'CARS'), ('MAN', 'MEN', 'ROAD', 'ROADS'), ('MAN', 'MEN', 'WOMAN', 'WOMEN'), ('MAN', 'MEN', 'BUILDING', 'BUILDINGS'), ('MAN', 'MEN', 'CAR', 'CARS'), ('MAN', 'MEN', 'CHILD', 'CHILDREN'), ('ROAD', 'ROADS', 'WOMAN', 'WOMEN'), ('ROAD', 'ROADS', 'BUILDING', 'BUILDINGS'), ('ROAD', 'ROADS', 'CAR', 'CARS'), ('ROAD', 'ROADS', 'CHILD', 'CHILDREN'), ('ROAD', 'ROADS', 'MAN', 'MEN'), ('WOMAN', 'WOMEN', 'BUILDING', 'BUILDINGS'), ('WOMAN', 'WOMEN', 'CAR', 'CARS'), ('WOMAN', 'WOMEN', 'CHILD', 'CHILDREN'), ('WOMAN', 'WOMEN', 'MAN', 'MEN'), ('WOMAN', 'WOMEN', 'ROAD', 'ROADS')]}])
evaluate_word_analogies方法采用了一個可選參數(shù)restrict_vocab,用于限制將考慮哪些測試樣本。
在2016年12月發(fā)布的Gensim中,我們添加了評估語義相似性的更好方法。
默認情況下,它使用學(xué)術(shù)數(shù)據(jù)集WS-353,但可以基于它創(chuàng)建特定于您的應(yīng)用的數(shù)據(jù)集。它包含單詞對和人為分配的相似性判斷。它測量兩個詞的相關(guān)性或共發(fā)生性。例如,"coast"和"shore"非常相似,因為它們出現(xiàn)在相同的上下文中。同時,"clothes"和"closet"則不那么相似,因為它們是相關(guān)的,但不可互換。
model.wv.evaluate_word_pairs(datapath('wordsim353.tsv'))
結(jié)果為:
((0.24489292949179034, 0.05931445733835701),
SpearmanrResult(correlation=0.1719049614621933, pvalue=0.18906147522805455),
83.0028328611898)
重要:在Google或WS-353測試集上的良好性能并不意味著word2vec在您的應(yīng)用中效果良好,反之亦然。最好直接評估您預(yù)期的任務(wù)。有關(guān)如何在分類器流管中使用 word2vec的示例,請參閱此教程。
在線訓(xùn)練/恢復(fù)訓(xùn)練(Online training / Resuming training)
高級用戶可以加載模型,并繼續(xù)使用更多的句子和新的詞匯來訓(xùn)練它:
model = gensim.models.Word2Vec.load(temporary_filepath)
more_sentences = [
['Advanced', 'users', 'can', 'load', 'a', 'model',
'and', 'continue', 'training', 'it', 'with', 'more', 'sentences'],
]
model.build_vocab(more_sentences, update=True)
model.train(more_sentences, total_examples=model.corpus_count, epochs=model.epochs)
# cleaning up temporary file
import os
os.remove(temporary_filepath)
根據(jù)你想要模擬的學(xué)習(xí)速度衰變,你可能需要調(diào)整total_words參數(shù)以進行訓(xùn)練(train())。
請注意,無法恢復(fù)使用C工具生成的模型的訓(xùn)練,KeyedVectors.load_word2vec_format()。你仍然可以使用它們進行查詢/相似性,但那里缺少對訓(xùn)練至關(guān)重要的信息(詞匯樹)。
訓(xùn)練損失計算(Training Loss Computation)
在訓(xùn)練Word2Vec模型時,參數(shù)compute_loss能夠用于開啟損失計算的開關(guān)。計算的損失被存儲在模型屬性running_training_loss,因此能夠被函數(shù)get_latest_training_loss按以下方式檢索:
# instantiating and training the Word2Vec model
model_with_loss = gensim.models.Word2Vec(
sentences,
min_count=1,
compute_loss=True,
hs=0,
sg=1,
seed=42,
)
# getting the training loss value
training_loss = model_with_loss.get_latest_training_loss()
print(training_loss)
結(jié)果為:
1370110.25
基準(zhǔn)集(Benchmarks)
讓我們運行一些基準(zhǔn)集來看看訓(xùn)練損失計算代碼對訓(xùn)練時間的影響。
我們將使用下面的數(shù)據(jù)作為基準(zhǔn)集:
- Lee Background corpus:包含在gensim的測試數(shù)據(jù)中
- Text8 corpus:我們展示語料庫大小的影響,我們將使用語料庫的前1MB、10MB、50MB,最后是整個語料庫。
import io
import os
import gensim.models.word2vec
import gensim.downloader as api
import smart_open
def head(path, size):
with smart_open.open(path) as fin:
return io.StringIO(fin.read(size))
def generate_input_data():
lee_path = datapath('lee_background.cor')
ls = gensim.models.word2vec.LineSentence(lee_path)
ls.name = '25kB'
yield ls
text8_path = api.load('text8').fn
labels = ('1MB', '10MB', '50MB', '100MB')
sizes = (1024 ** 2, 10 * 1024 ** 2, 50 * 1024 ** 2, 100 * 1024 ** 2)
for l, s in zip(labels, sizes):
ls = gensim.models.word2vec.LineSentence(head(text8_path, s))
ls.name = l
yield ls
input_data = list(generate_input_data())
我們現(xiàn)在比較輸入數(shù)據(jù)和模型訓(xùn)練參數(shù)(如hs和 sg)的不同組合所占用的培訓(xùn)時間。
對于每個組合,我們重復(fù)測試幾次,以獲得測試的平均值和標(biāo)準(zhǔn)偏差。
# Temporarily reduce logging verbosity
logging.root.level = logging.ERROR
import time
import numpy as np
import pandas as pd
train_time_values = []
seed_val = 42
sg_values = [0, 1]
hs_values = [0, 1]
fast = True
if fast:
input_data_subset = input_data[:3]
else:
input_data_subset = input_data
for data in input_data_subset:
for sg_val in sg_values:
for hs_val in hs_values:
for loss_flag in [True, False]:
time_taken_list = []
for i in range(3):
start_time = time.time()
w2v_model = gensim.models.Word2Vec(
data,
compute_loss=loss_flag,
sg=sg_val,
hs=hs_val,
seed=seed_val,
)
time_taken_list.append(time.time() - start_time)
time_taken_list = np.array(time_taken_list)
time_mean = np.mean(time_taken_list)
time_std = np.std(time_taken_list)
model_result = {
'train_data': data.name,
'compute_loss': loss_flag,
'sg': sg_val,
'hs': hs_val,
'train_time_mean': time_mean,
'train_time_std': time_std,
}
print("Word2vec model #%i: %s" % (len(train_time_values), model_result))
train_time_values.append(model_result)
train_times_table = pd.DataFrame(train_time_values)
train_times_table = train_times_table.sort_values(
by=['train_data', 'sg', 'hs', 'compute_loss'],
ascending=[False, False, True, False],
)
print(train_times_table)
結(jié)果為:
Word2vec model #0: {'train_data': '25kB', 'compute_loss': True, 'sg': 0, 'hs': 0, 'train_time_mean': 0.25217413902282715, 'train_time_std': 0.020226552024939795}
Word2vec model #1: {'train_data': '25kB', 'compute_loss': False, 'sg': 0, 'hs': 0, 'train_time_mean': 0.25898512204488117, 'train_time_std': 0.026276375796854143}
Word2vec model #2: {'train_data': '25kB', 'compute_loss': True, 'sg': 0, 'hs': 1, 'train_time_mean': 0.4194076855977376, 'train_time_std': 0.0021983060310549808}
Word2vec model #3: {'train_data': '25kB', 'compute_loss': False, 'sg': 0, 'hs': 1, 'train_time_mean': 0.4308760166168213, 'train_time_std': 0.0009999532723555815}
Word2vec model #4: {'train_data': '25kB', 'compute_loss': True, 'sg': 1, 'hs': 0, 'train_time_mean': 0.47211599349975586, 'train_time_std': 0.015136686417800442}
Word2vec model #5: {'train_data': '25kB', 'compute_loss': False, 'sg': 1, 'hs': 0, 'train_time_mean': 0.4695216814676921, 'train_time_std': 0.0033446725418043747}
Word2vec model #6: {'train_data': '25kB', 'compute_loss': True, 'sg': 1, 'hs': 1, 'train_time_mean': 0.9502590497334799, 'train_time_std': 0.005153258425238986}
Word2vec model #7: {'train_data': '25kB', 'compute_loss': False, 'sg': 1, 'hs': 1, 'train_time_mean': 0.9424160321553549, 'train_time_std': 0.009776048211734903}
Word2vec model #8: {'train_data': '1MB', 'compute_loss': True, 'sg': 0, 'hs': 0, 'train_time_mean': 0.6441135406494141, 'train_time_std': 0.00934594899599891}
Word2vec model #9: {'train_data': '1MB', 'compute_loss': False, 'sg': 0, 'hs': 0, 'train_time_mean': 0.656217098236084, 'train_time_std': 0.02703627277086478}
Word2vec model #10: {'train_data': '1MB', 'compute_loss': True, 'sg': 0, 'hs': 1, 'train_time_mean': 1.3150715033213298, 'train_time_std': 0.09457246701267184}
Word2vec model #11: {'train_data': '1MB', 'compute_loss': False, 'sg': 0, 'hs': 1, 'train_time_mean': 1.205832560857137, 'train_time_std': 0.005158620074483131}
Word2vec model #12: {'train_data': '1MB', 'compute_loss': True, 'sg': 1, 'hs': 0, 'train_time_mean': 1.5065066814422607, 'train_time_std': 0.036966116484319765}
Word2vec model #13: {'train_data': '1MB', 'compute_loss': False, 'sg': 1, 'hs': 0, 'train_time_mean': 1.537813663482666, 'train_time_std': 0.01020688183426915}
Word2vec model #14: {'train_data': '1MB', 'compute_loss': True, 'sg': 1, 'hs': 1, 'train_time_mean': 3.302257219950358, 'train_time_std': 0.04523242606424026}
Word2vec model #15: {'train_data': '1MB', 'compute_loss': False, 'sg': 1, 'hs': 1, 'train_time_mean': 3.4928714434305825, 'train_time_std': 0.19327551634697}
Word2vec model #16: {'train_data': '10MB', 'compute_loss': True, 'sg': 0, 'hs': 0, 'train_time_mean': 7.446084260940552, 'train_time_std': 0.7894319693665308}
Word2vec model #17: {'train_data': '10MB', 'compute_loss': False, 'sg': 0, 'hs': 0, 'train_time_mean': 7.060012976328532, 'train_time_std': 0.2136692186366028}
Word2vec model #18: {'train_data': '10MB', 'compute_loss': True, 'sg': 0, 'hs': 1, 'train_time_mean': 14.277136087417603, 'train_time_std': 0.7441633349142932}
Word2vec model #19: {'train_data': '10MB', 'compute_loss': False, 'sg': 0, 'hs': 1, 'train_time_mean': 13.758649031321207, 'train_time_std': 0.37393987718126326}
Word2vec model #20: {'train_data': '10MB', 'compute_loss': True, 'sg': 1, 'hs': 0, 'train_time_mean': 20.35730775197347, 'train_time_std': 0.41241047454786994}
Word2vec model #21: {'train_data': '10MB', 'compute_loss': False, 'sg': 1, 'hs': 0, 'train_time_mean': 21.380844751993816, 'train_time_std': 1.6909472056783184}
Word2vec model #22: {'train_data': '10MB', 'compute_loss': True, 'sg': 1, 'hs': 1, 'train_time_mean': 44.4877184232076, 'train_time_std': 1.1314265197889173}
Word2vec model #23: {'train_data': '10MB', 'compute_loss': False, 'sg': 1, 'hs': 1, 'train_time_mean': 44.517534812291466, 'train_time_std': 1.4472790491207064}
compute_loss hs sg train_data train_time_mean train_time_std
4 True 0 1 25kB 0.472116 0.015137
5 False 0 1 25kB 0.469522 0.003345
6 True 1 1 25kB 0.950259 0.005153
7 False 1 1 25kB 0.942416 0.009776
0 True 0 0 25kB 0.252174 0.020227
1 False 0 0 25kB 0.258985 0.026276
2 True 1 0 25kB 0.419408 0.002198
3 False 1 0 25kB 0.430876 0.001000
12 True 0 1 1MB 1.506507 0.036966
13 False 0 1 1MB 1.537814 0.010207
14 True 1 1 1MB 3.302257 0.045232
15 False 1 1 1MB 3.492871 0.193276
8 True 0 0 1MB 0.644114 0.009346
9 False 0 0 1MB 0.656217 0.027036
10 True 1 0 1MB 1.315072 0.094572
11 False 1 0 1MB 1.205833 0.005159
20 True 0 1 10MB 20.357308 0.412410
21 False 0 1 10MB 21.380845 1.690947
22 True 1 1 10MB 44.487718 1.131427
23 False 1 1 10MB 44.517535 1.447279
16 True 0 0 10MB 7.446084 0.789432
17 False 0 0 10MB 7.060013 0.213669
18 True 1 0 10MB 14.277136 0.744163
19 False 1 0 10MB 13.758649 0.373940
詞嵌入可視化(Visualising Word Embeddings)
模型生成的詞嵌入可以通過使用tSNE將單詞的維度降低到 2維來可視化。
可視化可用于注意數(shù)據(jù)中語義和語法的趨勢。
例如:
語義:單詞如cat、dog、cow等有靠攏的趨勢
語法:單詞如run、running或cut、cutting彼此靠近。
也可以注意到向量關(guān)系如vKing - vMan = vQueen - vWoman。
重要:可視化的模型在很小的語料庫上訓(xùn)練。因此,一些關(guān)系可能不是很清晰。
from sklearn.decomposition import IncrementalPCA # inital reduction
from sklearn.manifold import TSNE # final reduction
import numpy as np # array handling
def reduce_dimensions(model):
num_dimensions = 2 # final num dimensions (2D, 3D, etc)
# extract the words & their vectors, as numpy arrays
vectors = np.asarray(model.wv.vectors)
labels = np.asarray(model.wv.index_to_key) # fixed-width numpy strings
# reduce using t-SNE
tsne = TSNE(n_components=num_dimensions, random_state=0)
vectors = tsne.fit_transform(vectors)
x_vals = [v[0] for v in vectors]
y_vals = [v[1] for v in vectors]
return x_vals, y_vals, labels
x_vals, y_vals, labels = reduce_dimensions(model)
def plot_with_plotly(x_vals, y_vals, labels, plot_in_notebook=True):
from plotly.offline import init_notebook_mode, iplot, plot
import plotly.graph_objs as go
trace = go.Scatter(x=x_vals, y=y_vals, mode='text', text=labels)
data = [trace]
if plot_in_notebook:
init_notebook_mode(connected=True)
iplot(data, filename='word-embedding-plot')
else:
plot(data, filename='word-embedding-plot.html')
def plot_with_matplotlib(x_vals, y_vals, labels):
import matplotlib.pyplot as plt
import random
random.seed(0)
plt.figure(figsize=(12, 12))
plt.scatter(x_vals, y_vals)
#
# Label randomly subsampled 25 data points
#
indices = list(range(len(labels)))
selected_indices = random.sample(indices, 25)
for i in selected_indices:
plt.annotate(labels[i], (x_vals[i], y_vals[i]))
try:
get_ipython()
except Exception:
plot_function = plot_with_matplotlib
else:
plot_function = plot_with_plotly
plot_function(x_vals, y_vals, labels)
