往往更经典的工作越能让人敬重知识的力量!
在之前的文章从WE到BERT中已经详细讲解了介绍了word2vec的相关知识,本文主要是对word2vec、glove以及fasttext进行对比介绍、分析。
Word2vec
相信word2vec大家已经耳熟能详了吧(甚至有些人已经耳朵起茧了),但是MeteorMan在2019.11阅读了一篇深入解析word2vec的文章,让人不禁升起对于知识的敬畏,感叹:知道的越多,了解的越少!
word2vec包含两种结构,一种是Skip-gram结构,一种是CBOW结构,skip-gram结构是利用中间词预测上下文词,CBOW模型是利用上下文词预测中间词。这两种模型有三层,输入层,映射层,输出层,隐藏层是线性结构。
提升训练速度?
(1)层次softmax。层次softmax相对于普通softmax而言极大地减少了计算量,提升了训练速度。
层次softmax的基本思想:在训练词向量时,对于词典D中的任意一个词w,Huffman树种必然存在一条从根节点到词w对应节点的路径(且这条路径唯一)。在这条路径上存在若干分支,将每个分支看作一次二分类,每次分类产生一个概率,将这些概率依次累积起来就是所需的p(w | context(w))。 |
对普通的softmax来说,对字典中的每个词都要预测一下概率,如果字典中有一万个词,那在已知上下文预测中间词的任务中对每个term都要预测1万次再取概率最大的对应的词,而对于层次softmax来说,输出层不是简单的softmax,而是一棵霍夫曼树,霍夫曼树的叶节点的个数是字典大小,他从根节点开始算概率,每次进行一个二分类,每次取较大的概率对应的结点作为下一次二分类的根节点,他的时间复杂度就是树的深度,这个深度是远远小于字典大小的。
(2)负采样。负采样是噪声对比估计的一个简化版本,目的是提高训练速度并改善所得词向量的质量。举个例子:将句子中的某个词当做中心词,与其关联的词当做上下文词,这是一个正样本,而采用与正样本相同的上下文词,再从字典中随机选择一个词当做中心词,将这个样本当做负样本,这就是负采样。
词序信息是否包含?
单看CBOW的模型图,有上下文的词预测中间的词,而且还把上下文的词向量直接相加了,显然是丢掉了次序信息的,比如‘我爱你’和‘你爱我’这两句话用CBOW模型预测中间词‘爱’得到的结果肯定是一样的,因为‘我’和‘你’的词向量时一样的,在映射层相加的结果也是一样,后面肯定也是一样的,但是如果CBOW不包含词序信息,那这个模型训练出来的词向量为什么还这么好用呢?原因就在他的名字上面,CBOW名为连续词袋模型。
纯粹的词袋模型除了词频信息外没有其他信息,而连续词袋模型(CBOW)将句子按照固定size切分为若干窗口,针对每个窗口内部上下文直接相加而没有考虑词序,然而在窗口滑动过程中是按照通顺的自然语言顺序滑动的,或者样本就是按照一定的语序取出来的,所以最终得出的词向量中会包含一定的语序信息,只不过通过取样得到的语序信息对词向量的约束很小,不如在CBOW窗口内部加入ngram这种强约束得到的词序信息明确且强烈。
OK,这个问题明确了,CBOW模型窗口内部抛弃了词序信息,对语言来说语序是很重要的,‘我爱你’的词袋特征是‘我’ ‘爱’ ‘你’ ,‘你爱我’的词袋特征是‘你’ ‘爱’ ‘我’,这两个句子的特征是完全相同的,但是这两个句子的语义是不一样的,如果在CBOW窗口内加入ngram特征(比如2gram)就会得到额外的信息,第一个句子的2gram特征是‘我爱’和‘爱你’,第二个句子的特征是‘你爱’ 和‘爱我’,这样就把上下文完全相同的两个句子区分开了,这种做法就是fastText的做法。
Fasttext
fastText简单来说就是将句子中的每个词先通过一个lookup层映射成词向量,然后对词向量取平均作为真个句子的句子向量,然后直接用线性分类器进行分类,从而实现文本分类。在输入层输入的是句子的每个词及其句子对应的ngram特征。
这是对于句子结构简单的文本来说,但是这种方法显然没有考虑词序信息,对于那些对词序很敏感的句子分类任务来说(比如情感分类)fastText就不如有隐藏层等非线性结构的网络效果好,比如线面这几个句子是对词序很敏感的类型: ‘The movie is not very good , but i still like it . ’ ‘The movie is very good , but i still do not like it .’ ‘I do not like it , but the movie is still very good .’ 这几个句子的词序差不多,用到的词也差不多,但是表达的意思是完全相反的,如果直接把词向量取平均,显然得到的平均词向量也是相差不到,在经过线性分类器分类很容易把这两个不同的类别分到同一类里,所以fastText很难学出词序对句子语义的影响,对复杂任务还是需要用复杂网络学习任务的语义表达。
与word2vec相比为什么能进一步提升训练速度
(1)层次softmax。在fastText中,由于最终的输出是预测句子的标签,这是一个监督学习过程,所以在训练过程中已经知道了要计算哪一条路径的概率,这样在计算霍夫曼树的路径时只需要计算一条路径而不用计算全部路径,大大提高了计算效率,而在测试过程中,由于没有标签,不知道真实的路径,仍然需要将霍夫曼树的每一个叶节点对应的路径的概率算出来。 (2)哈希编码。将句子对应的ngram特征使用哈希编码,进一步提升存储效率。
fasttext为什么这么快
用fastText做文本分类的关键点是极大地提高了训练速度(在要分类的文本类别很多的情况下,比如500类),原因是在输出层采用了层级softmax,层级softmax如何提高训练速度在上面CBOW的层级softmax中已经介绍了,在这里就是将叶节点由词频变成文本分类数据集中每种类别的样本数量,霍夫曼树的结构也可以处理类别不均衡的问题(每种类别的样本数目不同),频繁出现类别的树形结构的深度要比不频繁出现类别的树形结构的深度要小,这也使得进一步的计算效率更高(意思是数目多的样本深度小,那很多样本都只需乘一次就把概率计算出来了,自然就快)。
fasttext与CBOW的区别
主要体现在3个方面:
(1)目的不一样。fastText是用来做文本分类的,虽然中间也会产生词向量,但词向量是一个副产物,是一个有监督模型;而CBOW就是专门用来训练词向量的工具,属于无监督模型。
(2)输入层不一样。fastText的输入层是一个句子的每个词以及句子的ngram特征,而CBOW的输入层只是中间词的上下文,与完整句子没有关系。
(3)输出层不一样。fastText的输出层是预测句子的类别标签,而CBOW的输出层是预测中间词。
fasttext可以做无监督吗
当然可以。无监督训练语料的构建只需要在之前带标注语料的基础上将标注信息删去即可。然后在fasttext的实例中将supervised方法设置为false,即设置无监督学习。然后通过skipgram或者CBOW设置需要用的算法,包括在lossName方法中设置损失函数为ns,即负采样。
具体实施可以参考这篇文章。
Glove
Glove这种训练词向量的方法的核心思想是通过对’词-词’共现矩阵进行分解从而得到词表示的方法。