gensim模型(1)——Word2Vec

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)均非常有用。

該教程:

  1. 介紹word2Vec作為傳統(tǒng)詞袋模型的改進
  2. 使用預(yù)訓(xùn)練的模型來展示一個word2Vec例子
  3. 演示從您自己的數(shù)據(jù)中訓(xùn)練新模型
  4. 演示加載和保存模型
  5. 介紹幾個訓(xùn)練參數(shù)以及其作用
  6. 介紹內(nèi)存要求
  7. 通過應(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)了兩者:

  1. Skip-grams (SG)
  2. 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)集:

  1. Lee Background corpus:包含在gensim的測試數(shù)據(jù)中
  2. 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)
sphx_glr_run_word2vec_001.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容