文章目录
在进入主题之前我们先了解两个概念:One-Hot编码与词嵌入
一. One-Hot 编码与词嵌入
1.1 One-Hot 编码
one-hot编码说白了就是用0,1两个数字来表示一个单词或者字符。比如我有10000个单词的corpus,然后love这个单词在语料库的顺序为1那么我可以用向量[1,0,0,0,0,…0]来表示单词love。如果要计算两个单词之间的距离那么直接计算必然是不好计算的,但是如果转换为one-hot编码来计算就方便很多了。
1.2 词嵌入
Word Representation
不知道看官老爷们有没有发现上述表示的向量非常稀疏只有1个1其余全为0,因此如果要计算两个单词的相似性是非常困难的,例如
[0 0 0 0 0 1 0 0 … 0] AND [0 0 1 0 0 0 0 0 … 0] = 0
car motorcycle
这两个单词是比较相似的,却不好计算相似性。那么有没有别的办法呢,其实对于相似的单词一般都有类似的上下文,因此我可以设置一个固定窗口大小来建立Co-occurence Matrix
图中建立起窗口大小为1 的共生矩阵,矩阵中数字代表两个单词出现在同一个窗口的频率,通过建立共生矩阵就可以很好的计算两个单词的 相似性了。
存在的问题:
1)矩阵的大小会随着词汇库的增加而增加
2)高纬度
3) 矩阵稀疏->鲁棒性较差
有没有什么办法可以降低词嵌入向量的维度且增加密度呢?
既然这么问了那答案肯定是有滴~
方法一:减少矩阵的维度
SVD of co-occurrence matrix X
这是线性代数的一个知识点,但是缺点是计算量很大,如果增加新的单词如何去做改变也是个问题。
方法二:直接学习->单词嵌入
词嵌入好处:
给定一个没有训练的语料库,为每一个单词生成包含语义信息的向量。
1)两个单词的语义相似性可以通过计算两个单词词向量的余弦
2)词向量是各种监督自然语言处理任务的强大特征,因为向量包含语义信息
3)通过神经网络将任何信息传播到它们之中,并在训练期间更新
下面进入到我们今天的主题-Word2Vec
二. Word2Vec
不知道小伙伴们有没有和我一样的疑惑,word2vec是用来干什么的,和rnn等之类的网络有什么联系,下面讲下个人的理解
Word2Vec是利用不断地学习去完善一个词嵌入矩阵,该矩阵每一个行可以表示语料库中的一个单词,且包含上下文语意信息。然后该词嵌入矩阵可以作为RNN,LSTM等网络的输入提高网络的鲁棒性。
本文主要介绍Word2Vec中的Skip-gram模型
2.1 Skip-Gram
Skip-gram模型是利用中心词来预测上下文,举个栗子吧!
比如中心词是“love” 那么我可以通过skip-gram模型预测上下文为"I" “you”等
下面给出Skip-gram模型图解与公式
该模型大致的流程是首先输入中心词car的one-hot编码,然后经过隐藏层h输出该单词的词嵌入向量,然后再与上下文(语料库中其他单词)进行softmax算出概率分布(与中心词是上下下文的概率)。
其中: h = x T W = W ( k , . ) : = v w I h=x^TW=W(k,.):=v_{w_I} h=xTW=W(k,.):=vwI
下面画重点!!!!!!!!!!!!!!!
其中W就是我们要学习的词嵌入矩阵。相信很多看官老爷们和我一样一开始看这个充满疑惑,我们的目标不是获得词嵌入向量吗,那么这里的W是怎么来的呢?这就是该模型的精辟之处,初始时我们需要初始化该W矩阵(可以采用随机初始化,xavier等方法);通过该矩阵之后得到输入中心词的词嵌入向量,例子如下:
然后与语料库中其他词做softmax运算得到中心词与其他词的是上下文的概率分布,如果窗口大小是2的话那么从概率分布中挑选4个(左2右2)概率最大的单词作为该中心词的上下文,因为在语料库中我们已经知道了中心词的上文,因此可以计算出损失函数,然后利用梯度下降不断去调整词嵌入矩阵W,最后通过不断的学习得到包含语义信息的词嵌入矩阵W,这就是Skip-gram模型的学习过程。
下面我们通过公式具体推导下Skip-gram训练的过程(作为了解的客官可以跳过😅)
h
=
x
T
W
=
W
(
k
,
.
)
:
=
v
w
I
h=x^TW=W(k,.):=v_{w_I}
h=xTW=W(k,.):=vwI
s j = h v w j ′ s_j=hv^{'}_{w_j} sj=hvwj′(计算得分,其中 v w j ′ v^{'}_{w_j} vwj′为语料库中其他单词的词嵌入向量)
损失函数如下:
这里做一个细节展开(字有点丑请见谅):
W i j ′ 指 的 是 模 型 图 中 W N x V ′ 中 第 j 列 向 量 ( 即 某 个 要 计 算 上 下 文 单 词 的 词 向 量 ) W^{'}_{ij}指的是模型图中W^{'}_{N x V}中第j列向量(即某个要计算上下文单词的词向量) Wij′指的是模型图中WNxV′中第j列向量(即某个要计算上下文单词的词向量)
W k i 指 的 是 模 型 图 中 W V x N 中 第 i 行 向 量 ( 即 中 心 词 的 词 向 量 ) W_{ki}指的是模型图中W_{V x N}中第i行向量(即中心词的词向量) Wki指的是模型图中WVxN中第i行向量(即中心词的词向量)
这里做一个扩展:
每次都对整个语料库做梯度下降,当遇到大量的语料库时计算量无疑是非常大的,Word2Vec的作者在其一篇paper中解决了这个问题,有3个创新点:
1.把常见的词组作为一个单词。
2.少采样常见的词 (比如:A the)
3.修改优化目标函数,这个策略称之为“Negative Sampling(负采样)“,使得每个训练样本只去更新模型中一小部分的weights。
值得注意的是 2和3 不仅仅减少了训练的计算量,而且提升了最后word vector的质量。
三. Glove
细心的看官会发现上面的Skip-gram模型没有利用统计的全局信息,这样的话如果语料库很小的话那么模型的效果会很不好,所有就有了Glove(Global Vectors ),下面就简单介绍下
P i j = P ( w j ∣ w i ) = X i j / X i P_{ij}=P(w_j|w_i)=X_{ij}/X_i Pij=P(wj∣wi)=Xij/Xi
P i j 表 示 的 是 单 词 P_{ij}表示的是单词 Pij表示的是单词 w j w_j wj出现在单词 w i w_i wi上下文的概率, X i j X_{ij} Xij表示单词 w j , w i w_j,w_i wj,wi在语料库中出现在一起的概率, X i 表 示 单 词 w i 在 语 料 库 中 出 现 的 次 数 X_i表示单词w_i在语料库中出现的次数 Xi表示单词wi在语料库中出现的次数
Glove模型要做的就是通过不断的学习使得两单词的词向量相乘近似等于 P i j P_{ij} Pij
因为 l o g ( X i ) 之 和 单 词 i 有 关 , 所 以 可 以 被 log(X_i)之和单词i有关,所以可以被 log(Xi)之和单词i有关,所以可以被 b i b_i bi吸收。
那么 f ( X i j ) f(X_{ij}) f(Xij)是用来干什么的呢?因此不加上 f ( X i j ) f(X_{ij}) f(Xij)的话每一个字所占的contribute都是一样的(矩阵中的权重),有些单词出现次数比较少权值会比较小,通过梯度下降学习的话可能会消失,因此我们希望通过 f ( X i j ) f(X_{ij}) f(Xij)来进行调整使得它的值稍微大点。
f ( X i j ) f(X_{ij}) f(Xij)需要满足的条件:
1) f ( 0 ) = 0 f(0)=0 f(0)=0
2) f ( x ) f(x) f(x)应该是非递减的,希望出现单词次数越多,对整个loss贡献会稍微大一点
3) f ( x ) f(x) f(x) 应该有个阈值,这样频繁的共现不会被过度加权
总结:
Glove 模型训练很快,在语料库很小的时候表现很好。
四. 利用gensim简单使用Word2Vec
from gensim.test.utils import common_texts, get_tmpfile
from gensim.models import Word2Vec
print(common_texts)
'''
[['human', 'interface', 'computer'],
['survey', 'user', 'computer', 'system', 'response', 'time'],
['eps', 'user', 'interface', 'system'], ['system', 'human', 'system', 'eps'],
['user', 'response', 'time'], ['trees'],
['graph', 'trees'], ['graph', 'minors', 'trees'], ['graph', 'minors', 'survey']]
'''
model = Word2Vec(common_texts, size=2, window=5, min_count=1, workers=4)
print(model.wv['computer'])
# [0.19709973 0.03296339]
"""
sentences:要分析的语料,是一个列表
size:词向量的维度,默认值是100。
windows:词向量上下文最大距离,默认为5
sg:如果是0, 则是CBOW模型,是1则是Skip-Gram模型,默认是0即CBOW模型。
hs:如果是0, 则是Negative Sampling,是1为Hierarchical Softmax
negative:即使用Negative Sampling时负采样的个数,默认是5。
min_count:需要计算词向量的最小词频,默认是5。小语料库可以调小。
iter: 随机梯度下降法中迭代的最大次数,默认是5。对于大语料,可以增大这个值。
alpha: 在随机梯度下降法中迭代的步长,默认是0.025
min_alpha: 算法在迭代的过程中逐渐减小到的最小步长
"""
欢迎对自然语言感兴趣的小伙伴一起升级打怪!