Word2Vec

  2019-4-10 


什么是词向量

一种词的表示方法。通常NLP中使用one-hot或词向量表示

one-hot即为一维一词,占用空间大,且无法体现词之间的关联性

于是使用词向量可以包含更多信息,且使得向量在空间的表示更稠密。

如何生成词向量

基于统计

略。

语言模型生成词向量

  • NNLM(neural network language model)

    0

    目标函数

    $L=\frac{1}{T}\Sigma^T_{t=1}f(w_t,w_{t-1},…,w{t-n+1})$

    这个函数即目标将每一步的文档集的平均输出概率最大化。

    但是这个模型在softmax层占用过多资源(与词表长度成正比)。

    这个模型虽然现在不使用了,但是却提出了一个很有意义的思路,embedding层,中间层,softmax层(除外)。后面word2vec会详细展开。

  • C&W

    基于NNLM改变了目标函数,$L=max(0,1-(g_{\theta,E}(s)-g_{\theta,E}(z)))$

    原NNLM 模型的目标是构建一个语言概率模型 ,而 C&W 则是以生成词向量为目标的模型。 在 NNLM 模型的求解中,最费时的部分当属隐藏层到输出层的权重计算(softmax层)。由于C&W 模型没有采用语言模型的方式去求解词语上下文的条件概率,而是直接对 n 元短语打分,这是一种更为快速获取词向量的方式。C&W 模型的核心机理是 : 如果 n 元短语在语料库中出现过,那么模型会给该短语打高分;如果是未出现在语料库中的短语则会得到较低的评分,将这两者的输出值差异最大化。

  • Word2Vec

    其中包含①CBoW ②skip gram

    • CBoW

      输入为上下文(窗口)的one-hot
      比如我们要预测 i love eating coffee里的eating
      则one hot编码: i :0001 love:0010 eating:0100 coffee:1000
      我们要输入eating的前后文(选择窗口),那么输入网络的就是 0001,0010,1000(对应三个块)

      word2vec

      模型结构:

      假设一共有$V$个单词,在one-hot表示下每个单词$V$维

      $W_{V×N}:$输入权值矩阵(所有输入共享一个矩阵,即词嵌入矩阵,查词表),$W_{N×V}’:$输出权值矩阵,最后一层为softmax激活函数

      前向计算过程:上下文单词乘以词嵌入矩阵得到各自的词向量,然后再隐层求和平均即为待预测单词的词向量。公式表达:中间的向量为$v$,表记当前词嵌入矩阵为$W$,输入表记为$i_1,i_2,i_3$,则:

      中间那块儿隐藏层得到的向量$v$就是预测词的词向量,为$N$维向量,通常$N<<V$(Word2vec模型中的隐藏层没有激活函数,只是对各输入向量乘以输入权值矩阵$W$之后进行线性求和)。

      由输入层到映射层,降低维度的过程($k \to N$),就是将one-hot转变为词向量的过程,也就是 word embedding(词嵌入)。之所以词向量能够保留上下文信息,就是因为在训练输入的时候,输入了其上下文信息。

      输入权值矩阵$W$是所有单词的word embedding,也叫做查找表(look up table),其将one-hot转化为对应的词向量,实际上该矩阵每一列就是对应one-hot序号的词向量。

      如何使用:我们保存了训练结束的$W$矩阵之后,在使用训练好的模型的时候,输入上下文one-hot就能得到对应的词向量了。

      如何训练/训练目标:让输入词映射到隐藏层(词向量)后乘以输出权值矩阵$W’$,能够以最大概率准确输出输入词(也就是说输入经过这个word2vec模型并反向输出之后能还原回来,也就相当于信息无损压缩/嵌入后又能正确还原)

      具体地,就是要最大化在给定输入词和前后文本情况下输出正确关键词的概率,比如i love eating coffee中,要最大化输出eating的概率,就是要最大化$P(eating|i,love,coffee)$

      具体如何训练:对乘以$W’$获取的输出,概率最大的index所指示的单词为预测出的中间词,与原输入词的one-hot做比较,根据误差反向传播更新权重矩阵。

      举例:比如输入为的关键词one-hot为[0,0,0,1](略去上下文),经过$W’$并映射到隐藏层(词向量)又经过$W’$后,输出为[0.2,0.3,0.1,0.4],那么损失函数就是计算[0.2,0.3,0.1,0.4][0,0,0,1]的损失,尽量减小这个损失。

      • skip gram

        输入为一个词的one-hot,输出为多个词的one-hot(上下文),然后BP训练即可,相当于CBoW结构反过来,学的依然是$W$权重

        训练目标:比如输入eating,求上下文,那么就是最大化$P(i|eating),P(i|love),P(i|coffee)$

补充:torch.nn.Embedding 与 词嵌入的实际使用

词嵌入层

word2vec就是一种词嵌入算法

为什么我们在RNN模型外面对语料做了一次word2vec词嵌入,但再输入进RNN模型之前有还有一个词嵌入层呢?且这个词嵌入层的参数是需要训练学习的。

因为通常word2vec一般只做nn.embedding的初始化。在输入进RNN之前再加一层词嵌入层即nn.Embedding,其目的是让词嵌入向量继续随着模型训练而变化

为什么呢?我们word2vec可能是用了别人的词向量表(如我在项目中用的腾讯词向量表),但我们还需要根据我们的特定任务进行特化,所以我们在RNN网络之前再加一层词嵌入层,让模型根据实际任务去学习词嵌入(学习到的就是这层的参数:词嵌入矩阵)

我们也可以不用两个词嵌入层,其中一个也行,但实验效果会比较差,我在项目中第一次用腾讯w2v+LSTM效果很差应该就是这个原因。

具体参数:

torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False)

这是一个矩阵类,里面初始化了一个随机矩阵,矩阵的长是字典的大小(词表长度),宽是目标的词嵌入向量长度,向量的维度根据你想要表示的元素的复杂度而定。类实例化之后可以根据字典中元素的下标来查找元素对应的向量。(长宽位置是否调换取决于输入向量格式,总之得到词向量是一个一维向量)


且听风吟