一、概述GloVe与word2vec
GloVe与word2vec,两个模型都可以根据词汇的“共现co-occurrence”信息,将词汇编码成一个向量(所谓共现,即语料中词汇一块出现的频率)。
两者最直观的区别在于,word2vec是“predictive”的模型,而GloVe是“count-based”的模型。
Predictive的模型,如Word2vec,根据context预测中间的词汇,要么根据中间的词汇预测context,分别对应了word2vec的两种训练方式cbow和skip-gram。
对于word2vec,采用三层神经网络就能训练,最后一层的输出要用一个Huffuman树进行词的预测。
Count-based模型,如GloVe,本质上是对共现矩阵进行降维。首先,构建一个词汇的共现矩阵,每一行是一个word,每一列是context。共现矩阵就是计算每个word在每个context出现的频率。
由于context是多种词汇的组合,其维度非常大,我们希望像network embedding一样,在context的维度上降维,学习word的低维表示。
这一过程可以视为共现矩阵的重构问题,即reconstruction loss。
这里再插一句,降维或者重构的本质是什么?我们选择留下某个维度和丢掉某个维度的标准是什么?
--- Find the lower-dimensional representations which can explain most of the variance in the high-dimensional data,这其实也是PCA的原理。
两种方法都能学习词的向量表示,在real world application中,他们效果上有啥差别呢?
答案是performance上差别不大。
两个模型在并行化上有一些不同,即GloVe更容易并行化,所以对于较大的训练数据,GloVe更快。
在英文上,glove for GloVe 和 gensim for word2vec是常用的训练词向量的python package,完全可以使用自己的训练语料训练词向量。
当然,他们都提供了google news(英文)上训练好的词向量,大家完全可以下载下来,直接使用。对于中文的训练语料,可以使用sogou中文新闻语料。
二、深入解剖word2vec
1、word2vec的两种模型分别是什么?
word2Vec 有两种模型:CBOW 和 Skip-Gram:
- CBOW 在已知
context(w)
的情况下,预测 w
; - Skip-Gram在已知
w
的情况下预测 context(w)
;
word2vec
与NNLM相比,word2vec的主要目的是生成词向量而不是语言模型,在CBOW中,投射层将词向量直接相加而不是拼接起来,并舍弃了隐层,这些牺牲都是为了减少计算量,使训练更加
2、word2vec的两种优化方法是什么?它们的目标函数怎样确定的?训练过程又是怎样的?
不经过优化的CBOW和Skip-gram中 ,在每个样本中每个词的训练过程都要遍历整个词汇表,也就是都需要经过softmax归一化,计算误差向量和梯度以更新两个词向量矩阵(这两个词向量矩阵实际上就是最终的词向量,可认为初始化不一样),当语料库规模变大、词汇表增长时,训练变得不切实际。为了解决这个问题,word2vec支持两种优化方法:hierarchical softmax 和negative sampling。此部分仅做关键介绍,数学推导请仔细阅读《word2vec 中的数学原理详解》。
(1)基于hierarchical softmax 的 CBOW 和 Skip-gram
基于hierarchical softmax 的 CBOW 和 Skip-gram
hierarchical softmax 使用一颗二叉树表示词汇表中的单词,每个单词都作为二叉树的叶子节点。对于一个大小为V的词汇表,其对应的二叉树包含V-1非叶子节点。假如每个非叶子节点向左转标记为1,向右转标记为0,那么每个单词都具有唯一的从根节点到达该叶子节点的由{0 1}组成的代号(实际上为哈夫曼编码,为哈夫曼树,是带权路径长度最短的树,哈夫曼树保证了词频高的单词的路径短,词频相对低的单词的路径长,这种编码方式很大程度减少了计算量)。
CBOW中的目标函数是使条件概率 最大化,其等价于:
Skip-gram中的目标函数是使条件概率 最大化,其等价于:
(2)基于negative sampling的 CBOW 和 Skip-gram
negative sampling是一种不同于hierarchical softmax的优化策略,相比于hierarchical softmax,negative sampling的想法更直接——为每个训练实例都提供负例。
对于CBOW,其目标函数是最大化:
对于Skip-gram,同样也可以得到其目标函数是最大化:
负采样算法实际上就是一个带权采样过程,负例的选择机制是和单词词频联系起来的。
具体做法是以 N+1
个点对区间 [0,1]
做非等距切分,并引入的一个在区间 [0,1]
上的 M
等距切分,其中 M >> N。
源码中取 M = 10^8。然后对两个切分做投影,得到映射关系:采样时,每次生成一个 [1, M-1] 之间的整数 i,则 Table(i) 就对应一个样本;当采样到正例时,跳过(拒绝采样)。
三、深入解剖Glove详解
GloVe的全称叫Global Vectors for Word Representation,它是一个基于全局词频统计(count-based & overall statistics)的词表征(word representation)工具。
1、GloVe构建过程是怎样的?
(1)根据语料库构建一个共现矩阵,矩阵中的每一个元素 代表单词 和上下文单词 在特定大小的上下文窗口内共同出现的次数。
(2)构建词向量(Word Vector)和共现矩阵之间的近似关系,其目标函数为:
这个loss function的基本形式就是最简单的mean square loss,只不过在此基础上加了一个权重函数 :
根据实验发现 的值对结果的影响并不是很大,原作者采用了 。而 时的结果要比 时要更好。下面是 时 的函数图象,可以看出对于较小的 ,权值也较小。这个函数图像如下所示:
2、GloVe的训练过程是怎样的?
- 实质上还是监督学习:虽然glove不需要人工标注为无监督学习,但实质还是有label就是 。
- 向量 和 为学习参数,本质上与监督学习的训练方法一样,采用了AdaGrad的梯度下降算法,对矩阵 中的所有非零元素进行随机采样,学习曲率(learning rate)设为0.05,在vector size小于300的情况下迭代了50次,其他大小的vectors上迭代了100次,直至收敛。
- 最终学习得到的是两个词向量是 和 ,因为 是对称的(symmetric),所以从原理上讲 和 ,是也是对称的,他们唯一的区别是初始化的值不一样,而导致最终的值不一样。所以这两者其实是等价的,都可以当成最终的结果来使用。但是为了提高鲁棒性,我们最终会选择两者之和 作为最终的vector(两者的初始化不同相当于加了不同的随机噪声,所以能提高鲁棒性)。
3、Glove损失函数是如何确定的?(来自GloVe详解)
Glove与Word2vec比较:
- Word2vec是局部语料库训练的,其特征提取是基于滑窗的;而glove的滑窗是为了构建co-occurance matrix(上面详细描述了窗口滑动的过程),统计了全部语料库里在固定窗口内的词共线的频次,是基于全局语料的,可见glove需要事先统计共现概率;因此,word2vec可以进行在线学习,glove则需要统计固定语料信息。
- Word2vec是无监督学习,同样由于不需要人工标注,glove通常被认为是无监督学习,但实际上glove还是有label的,即共现次数log(X_i,j)
- Word2vec损失函数实质上是带权重的交叉熵,权重固定;glove的损失函数是最小平方损失函数,权重可以做映射变换。
- Glove利用了全局信息,使其在训练时收敛更快,训练周期较word2vec较短且效果更好。
更多关于GloVe和word2vec的区别详见论文:
参考链接:https://zhuanlan.zhihu.com/p/31023929
一、什么是tf-idf?
- tf(Term Frequency)词频:指的是某一个给定的词语在该文件中出现的次数。这个数字通常会被归一化(一般是词频除以文章总词数), 以防止它偏向长的文件。
- idf(Inverse Document Frequency)逆文档频率:log(语料库的文档总数/包含该词的文档数)
- 特点:1. 可用某篇文章中出现次数多但在其他文章中出现次数少的词来作为该篇文章的特征词。2. 使罕见的单词更加突出并且有效地忽略了常用单词 3. 易于理解
- 缺点:1. 因为是词袋模型,所以没有考虑词的位置信息,但词的位置是有一定含义的。2. 并不能反映单词的重要程度和特征词的分布情况。
二、各种词向量的特点:
- One-hot:维度灾难 and 语义鸿沟
- 矩阵分解(LSA):利用全局语料特征,但SVD求解计算复杂度大
- 基于NNLM/RNNLM的词向量:词向量为副产物,存在效率不高等问题
- word2vec、fastText:优化效率高,但是基于局部语料
- glove:基于全局预料,结合了LSA和word2vec的优点
- elmo、GPT、bert:动态特征
三、NNLM(参考链接:http://www.pengjingtian.com/2016/09/17/nnlm/):
- 神经网络语言模型:利用语言模型产生词向量,详细点说就是利用上下文词预测中心词或利用前n个词预测下一个词,词向量只是副产物
- 初始化一个V*D的词向量矩阵,其中V是语料库词汇表的大小,D是词向量的维度,随机初始值
- 输入层:利用n个上下文词的one-hot编码与词向量矩阵相乘,找到每个单词的词向量,拼接起来,成为一个更长的向量,即D*n维向量
- 隐藏层:将D*n维向量经过线性层转换为M维向量,再经过tanh等激活函数
- 输出层:再把M维向量经过线性层转换为大小为V维的向量,经过softmax函数即可得到每一个词的概率
- 其训练目标是最大化似然函数
四. Word2vec和nnlm的对比:
- 两者本质都是语言模型
- 词向量只是nnlm的一个产物,虽说word2vec本质也是语言模型,但其更专注于词向量本身,所以有一些优化算法来提高计算效率
- 具体计算方面,在利用上下文词预测中心词时,nnlm是把上下文词的向量进行拼接,word2vec是进行sum,并舍弃隐藏层(为了减少计算量)
- word2vec的两个加速算法:hierarchical softmax 和negative sampling
五、深入剖析word2vec(参考链接:https://blog.csdn.net/itplus/article/details/37969519):
- 两种模型 and 两种优化算法:
- CBOW(连续词袋模型):利用上下文词预测中心词
- Skip-gram(跳字模型):利用中心词预测上下文词
- hierarchical softmax(层次softmax)
- negative sampling(负采样)
六. 深入剖析Fasttext(参考链接:https://zhuanlan.zhihu.com/p/32965521):
- 模型架构:
- 与word2vec的CBOW类似
- 输入层:词和子词(subword)的n-gram的特征向量
- 隐藏层:所有词的向量叠加求平均之后经过线性变换到隐藏层
- 输出层:Hierarchical Softmax输出文本类别
- 两个特色:
- 字符级的n-gram:除了每个单词的词向量外,还为每个单词的n-gram字符添加一个向量,作为额外的特征,两点好处:
- 对于低频词生成的词向量效果会更好。因为它们的n-gram可以和其它词共享。
- 对于训练词库之外的单词,仍然可以构建它们的词向量。我们可以叠加它们的字符级n-gram向量。
- 分层softmax:利用哈夫曼树构建,根据目标类别的多少自上而下构建,数目越多的类越在顶部。(与word2vec里类似)
2. 核心思想:将整篇文档的词及n-gram向量叠加平均得到文档向量,然后使用文档向量做softmax多分类。这中间涉及到两个技巧:字符级n-gram特征的引入以及分层Softmax分类。
3. 为什么fasttext会快:
- hierarchical softmax 和negative sampling是对普通softmax的极大提速
- hs里使用huffman树,做分类一般类别没那么多,叶子节点相对word2vec(每个目标词一个叶子节点)少很多。并且语料每一行只训练一次,word2vec要每个中心词训练一次,训练次数又少了很多。当然fasttext可以设置epoch训练多轮
- 各种提速的trick,比如提前算好exp的取值之类的,这点和word2vec是一样的了
七. Fasttext与Word2vec比较:
- 都可以无监督学习词向量, fastText训练词向量时会考虑subword
- fastText还可以进行有监督学习进行文本分类
- 都利用了hierarchical softmax进行加速
- Fasttext引入字符级n-gram可以处理长词,未出现过的词,以及低频词
八. Elmo(Embeddings from Language Models)详解(参考链接:https://www.jiqizhixin.com/articles/2019-04-22-3):
- 模型结构(如图):
- 首先使用字符级卷积神经网络(convolutional neural network, CNN)来将文本中的词转换成原始词向量(raw word vector)
- 将这些原始词向量输入双向语言模型中第一层
- 前向迭代中包含了该词以及该词之前的一些词汇或语境的信息
- 后向迭代包含了该词之后的信息
- 这两种迭代的信息组成了中间词向量(intermediate word vector)
- 这些中间词向量被输入到模型的下一层
- 最终表示(ELMo)就是原始词向量和两个中间词向量的加权和
2. 训练过程:
- 首先明确LSTM 每一个时间点都会有一个输出,不要把这个输出和向下一时间点传送的记忆内容搞混,两个是有区别的,LSTM向下一个时间点传送的东西有两个,一个是该时间点的输出也就是隐状态H,同时传给了下一个时间点,另一个是记忆单元C,每个时间点的输出只有H(如图)。
- 理解了LSTM的输出后,再来看一层双向LSTM就会有两个输出,一个来自正向,一个来自负向,这两个一个代表前面信息对该词的影响的输出,一个代表后面信息对该词影响的输出,都能拿来当作词向量用,所以一层就会有两个词向量,两层就有4个,再加上最开始的输入,raw word vectors,就有4+1,也就有了2L+1个词向量!!!
- 再来理解一下RNN的提出,RNN的提出本身就是为了解决序列信息的问题(在NLP中),普通神经网络在操作时,后面的输入和前面的输入都是无关的,所以RNN本身就可以拿来做语言模型,我们也做过用LSTM/GRU或普通RNN来直接做语言模型的。
- 理解了RNN语言模型,那Elmo就很简单了,就是个多层的LSTM来用作训练语言模型。
- 具体公式如图,目标就是最小化损失函数,反向传播更新就完事了: