word2vec简单总结

一、Skip-Gram

Skip-Gram 模型假设中心词可以用来生成上下文词。

词表中的每个词都由两个 d d d 维向量来表示,具体来说,对于索引为 i i i 的词,我们分别用 v i , u i boldsymbol{v}_i,boldsymbol{u}_i vi​,ui​ 表示其用作中心词和上下文词的两个向量。

设词 w o w_o wo​ 位于中心词 w c w_c wc​ 的上下文窗口内,则

P ( w o ∣ w c ) = exp ⁡ ( u o ′ v c ) ∑ i ∈ V exp ⁡ ( u i ′ v c ) P(w_o|w_c)=frac{exp(boldsymbol{u}_o'boldsymbol{v}_c)}{sum_{iin mathcal{V}}exp(boldsymbol{u}_i'boldsymbol{v}_c)} P(wo​∣wc​)=∑i∈V​exp(ui′​vc​)exp(uo′​vc​)​

其中 V = { 0 , 1 , ⋯   , ∣ V ∣ − 1 } mathcal{V}={0,1,cdots,|mathcal{V}|-1} V={0,1,⋯,∣V∣−1} 是词表的索引集。

设上下文窗口大小为 m m m,则 Skip-Gram 模型的似然函数为

L = ∏ t = 1 T ∏ − m ≤ j ≤ m , j ≠ 0 P ( w t + j ∣ w t ) mathcal{L}=prod_{t=1}^T prod_{-mleq jleq m,jneq 0}P(w_{t+j}|w_t) L=t=1∏T​−m≤j≤m,j=0∏​P(wt+j​∣wt​)

最大化 L mathcal{L} L 等价于最小化 − log ⁡ L -logmathcal{L} −logL,即

− ∑ t = 1 T ∑ − m ≤ j ≤ m , j ≠ 0 log ⁡ P ( w t + j ∣ w t ) -sum_{t=1}^Tsum_{-mleq jleq m,jneq 0}log P(w_{t+j}|w_t) −t=1∑T​−m≤j≤m,j=0∑​logP(wt+j​∣wt​)

二、CBOW

与 Skip-Gram 相反,CBOW 模型假设上下文词可以用来生成中心词。

设上下文窗口大小为 m m m,则上下文词的数量为 2 m 2m 2m。在计算条件概率时我们通常会对这些上下文词取平均,即

v o ‾ = 1 2 m ∑ 1 ≤ ∣ i ∣ ≤ m v c + i overline{boldsymbol{v}_o}=frac{1}{2m}sum_{1leq|i|leq m}boldsymbol{v}_{c+i} vo​​=2m1​1≤∣i∣≤m∑​vc+i​

记 W o ( c ) = { v c − m , ⋯   , v c − 1 , v c + 1 , ⋯   , v c + m } mathcal{W}_{o(c)}={boldsymbol{v}_{c-m},cdots,boldsymbol{v}_{c-1},boldsymbol{v}_{c+1},cdots,boldsymbol{v}_{c+m}} Wo(c)​={vc−m​,⋯,vc−1​,vc+1​,⋯,vc+m​},则

P ( w c ∣ W o ( c ) ) = exp ⁡ ( u c ′ v o ‾ ) ∑ i ∈ V exp ⁡ ( u i ′ v o ‾ ) P(w_c|mathcal{W}_{o(c)})=frac{exp(boldsymbol{u}_c'overline{boldsymbol{v}_o})}{sum_{iinmathcal{V}}exp(boldsymbol{u}_i'overline{boldsymbol{v}_o})} P(wc​∣Wo(c)​)=∑i∈V​exp(ui′​vo​​)exp(uc′​vo​​)​

CBOW 模型的似然函数为

L = ∏ t = 1 T P ( w c ∣ W o ( c ) ) mathcal{L}=prod_{t=1}^T P(w_c|mathcal{W}_{o(c)}) L=t=1∏T​P(wc​∣Wo(c)​)

三、Gensim实现

? 相关文档:https://radimrehurek.com/gensim/models/word2vec.html

先导入接下来所需要用到的包:

from gensim.models import Word2Vec, KeyedVectors
from gensim.test.utils import common_texts
import gensim.downloader as api

我们可以使用 gensim 自带的 Word2Vec 来实现相关计算:

sentences = [['first', 'sentence'], ['second', 'sentence']]
# 词向量维度是5
# 出现次数低于1的单词会被丢弃
# 使用4个线程训练
model = Word2Vec(sentences=sentences, vector_size=5, min_count=1, workers=4)
word_vectors = model.wv
# 训练结束后可查看词向量
print(word_vectors['sentence'])
# [-0.01072454  0.00472863  0.10206699  0.18018547 -0.186059  ]

训练完成后,可以保存模型以便下次使用

model.save('word2vec.model')  # 保存模型
model = Word2Vec.load('word2vec.model')  # 读取模型

当然也可以保存训练好的词向量

word_vectors.save("word2vec.wordvectors")  # 保存词向量
word_vectors = KeyedVectors.load("word2vec.wordvectors", mmap='r')  # 读取词向量,r代表只读

我们还可以查看与某个单词最相似的几个单词

model = Word2Vec(sentences=common_texts, vector_size=5, min_count=1)
sims = model.wv.most_similar('computer', topn=3)
print(sims)
# [('minors', 0.4151746332645416), ('time', 0.18495501577854156), ('interface', 0.05030104145407677)]

使用现成的预训练模型:

word_vectors = api.load('glove-twitter-25')
print(word_vectors.most_similar('twitter', topn=10))
# [('facebook', 0.948005199432373), ('tweet', 0.9403423070907593), ('fb', 0.9342358708381653), ('instagram', 0.9104824066162109), ('chat', 0.8964965343475342), ('hashtag', 0.8885937333106995), ('tweets', 0.8878158330917358), ('tl', 0.8778461217880249), ('link', 0.877821147441864), ('internet', 0.8753896355628967)]