《How to Generate a Good Word Embedding?》导读

  自认为这是一篇有用的文章,因此在发表之前先放到 arXiv 上,供大家参考,请批评指正。
  论文地址:http://arxiv.org/abs/1507.05523
  实验代码地址:https://github.com/licstar/compare

  准备这篇论文大概花了半年时间,从去年 11 月开始做实验,到今年成文。期间消耗大约 10 万 CPU 小时,然后在几十万个结果里面做人肉数据挖掘,最后得到了一些可能有用的结论。

  看标题就能够猜到论文的大概内容了,就是希望找到一种简单有效的词向量学习方法。怎么会想到做这件苦逼的事情呢?半年之前在我准备上一篇论文的时候(RCNN,强行广告,欢迎引用,文章点此,上面的常用链接里有文章相关信息)有一个意外的发现:选用不同的词向量作为模型的初始值,效果的差异非常大!!!当时正值我已经调了好几天参数,黔驴技穷之时,没想到手滑用错了个词向量,效果突然变 NB 了。这下我就脑洞大开了,要是能搞出个宇宙第一词向量,岂不是以后可以随便灌水?后面的故事肯定就能猜到了,半年之前我掉进这个坑里,只为寻找这个“宇宙第一”词向量。然后我实现了几个主流的词向量模型,遍历了各种语料和参数,榨干了实验室机器的空闲资源跑词向量,从生成的几十万个词向量里寻找规律,最后发现“宇宙第一”词向量应该是不存在的,不过生成一个好用的词向量还是有一定套路可循的。为避免某些读者对后面冗长的文字没有兴趣,我先用最简单的话描述我们发现的这个套路,那就是:

首先根据具体任务,选一个领域相似的语料,在这个条件下,语料越大越好。然后下载一个 word2vec 的新版(14年9月更新),语料小(小于一亿词,约 500MB 的文本文件)的时候用 Skip-gram 模型,语料大的时候用 CBOW 模型。最后记得设置迭代次数为三五十次,维度至少选 50,就可以了。

  似乎结论很“显然”,不过这种简单的策略,真的就这么有效吗?word2vec 在半年前已经是最流行的词向量生成工具了,它之所以能这么流行,除了头上顶着 Google 光环,很大程度上是因为这是一个好用的工具包,而不一定是因为它的效果就是最好的。质疑 word2vec 的效果,是因为它的两个模型(Skip-gram 和 CBOW)相对前人的模型做了大量简化,去掉了词序,又去掉了神经网络的隐藏层,最后变成了一个 log 线性模型。我主观地认为,这些简化是会影响词向量的性能的,毕竟词序很有用(上面提到的我的上一篇论文就是讲这个的,再次广告);然后神经网络的表达能力也比 logistic 回归要强得多。这两部分简化到底会带来多少损失,还是要靠数据来说话。所以我考虑的第一个问题就是,什么模型效果好。前面博客提到过的经典模型(NNLM、LBL、C&W)在 word2vec 出现之前,是最主流的方法。这些方法就保留了词序信息,而且也有隐藏层,都放到一起比较。有了这些模型,还缺一个只保留词序,但没有隐藏层的模型。所以我设计了一个中间模型,叫 Order,保留了词序,但没有隐藏层。最后再加上开源的 GloVe,一共比较了 Skip-gram、CBOW、Order、LBL、NNLM、C&W、GloVe 这 7 个模型。

  那么最严峻的问题来了,怎么样才算好的词向量呢,应该用什么指标来衡量呢?Mikolov 推广 word2vec 的时候,设计了一个经典的指标(king-queen=man-woman),由于有开放的数据集和评测代码,后来大量的工作都只用这一个指标来评价词向量。我觉得只用这个指标肯定是不对的,为什么词向量非得有这种线性平移的特性啊,如果说这是个加分项,还说得过去,但要成为唯一衡量标准,似乎没什么道理。我觉得 GloVe 那篇论文就做的很好,里面比较了一大堆指标。所以我就从根源想起,我们拿词向量是用来干什么呢?①有人拿它寻找近义词或者相关词,直接根据向量空间里的距离远近来判定词的关系。②也有不少早期的工作,直接拿词向量做特征,在现有系统中加入词向量作为特征。特征嘛,就是要个多样性,虽然不知道词向量包含了什么信息,但是说不定就带着新的信息,效果就能提升了。③还有大量基于神经网络的工作,拿词向量作为神经网络的初始值。神经网络的初始值选得好,就有可能收敛到更好的局部最优解。好,就是这三种指标了:语义特性、用作特征、用作初始值。基于这三大类用法,我们具体找了 8 个指标,进行比较,综合评价词向量的性能。(题外话,其实我从一开始就很想找到一个终极指标,用一个指标定江山,但是自从看到这 8 个指标的结果如此不一致之后,我终于放弃了这个念头。)

  为了公平的比较,肯定需要设定一个相同的语料,所有模型都用同样的语料来训练。选个什么语料呢?脑海中的第一反应是:大语料。其实小规模语料(几十兆) Turian 在 2010 年已经做过一些实验了,比较了 C&W 和 HLBL 这两个模型。大规模语料下,结论会不会不一样呢?找了两个大语料,维基百科英文版和纽约时报。此前,主流论点是:语料越大越好。所有语料都堆到一起,不管是什么内容,我语料越大,涵盖的语义信息就越丰富,效果就越好。GloVe 和 C&W 都是这么干的。自然,我也把这两个大语料混合在一起训练了。同时由于好奇心,我还把这两个语料单独拿出来训练词向量。反正就是挂机跑嘛。另一方面,为了验证一下是不是真的语料越大越好,我也在大语料中抽了 10M、100M、1G 词的子集,顺便验证一下别人的结论。说到这里我忍不住剧透了,实验中最意外的结果就是,语料对词向量的影响比模型的影响要重要得多得多得多(重要的事说三遍)。本来我只想固定一个语料,公平比较模型,结果却发现语料比模型重要(抱歉,是四遍)……后来又加了一个小规模的 IMDB 语料,进一步证实了这个结论。实验结果就是这样。

  当然,为了公平比较,还有一些其它的因素需要考虑,比如上下文窗口都开成一样大,词向量的维度也需要统一。还有个很重要的参数,那就是迭代次数。这些词向量模型都是用迭代方法优化的,迭代次数肯定会影响性能。对所有模型固定迭代次数可能不合适,毕竟模型之间的差异还是蛮大的。所以为了省事,我们对所有实验迭代足够多的次数,从 100 次到 10000 次,取最好的那次。做了这个决定之后,人省事了,机器累死了,而且对于每个语料、每个模型、每个参数,还要保留不同迭代次数的词向量,很快就把 3T 硬盘塞满了……一边删数据,一边继续做实验……这种暴力手段肯定是不适合实际应用的,所以我们也努力从实验数据中寻找规律,希望找到一种合适的迭代停止条件。

  最后总结一下,我们认为模型、语料、参数三方面会影响词向量的训练,所以从这三方面入手分析到底应该怎么生成一个好的词向量,论文由此展开。在博客里主要就介绍一下不方便写进论文里的故事和背景。

—————-枯燥开始的分割线—————-

  简单列举一下文章的贡献。
  模型方面,因为所有的词向量模型都是基于分布式分布假说的(distributional hypothesis):拥有相似上下文的词,词义相似。这里有两个对象,一个是我们需要关注的词(目标词),另一个是这个词对应的上下文。所以,我们从两个角度去总结模型:1.目标词和上下文的关系,2.上下文怎么表示。在这种分类体系下,我们对现有的主流词向量模型进行了总结和比较,发现,目标词和上下文的关系主要有两种,大多数模型都是根据上下文,预测目标词。而 C&W 模型则是对目标词和上下文这一组合,打分。实验发现,通过上下文预测目标词的模型,得到的词向量,更能捕获替换关系(paradigmatic)。在上下文的表示方面,我们分析了几种表示方法之后,发现可以通过模型复杂程度对这些模型进行排序。排序之后,实验结果就容易解释了:简单的模型(Skip-gram)在小语料下表现好,复杂的模型在大语料下略有优势。从实践中看,word2vec 的 CBOW 模型在 GB 级别的语料下已经足够好。我前面提到的 Order 模型,加入了词序信息,其实很多时候比 CBOW 更好,不过带来的提升并不大。

  语料方面,很多论文都提到语料越大越好,我们发现,语料的领域更重要。领域选好了,可能只要 1/10 甚至 1/100 的语料,就能达到一个大规模泛领域语料的效果。有时候语料选的不对,甚至会导致负面效果(比随机词向量效果还差)。文章还做了实验,当只有小规模的领域内语料,而有大规模的领域外语料时,到底是语料越纯越好,还是越大越好。在我们的实验中,是越纯越好。这一部分实验数据比较丰富,原文相对清楚一些。

  参数方面,主要考虑了迭代次数和词向量的维度。其实词向量都是迭代算法,一般迭代算法都需要多迭代几次。旧版的 word2vec 只迭代了一次,效果很受限制,换新版就好了(也欢迎用我们论文实验的方法,用 AdaGrad 优化,相比原版 word2vec 的学习速率下降法,这样还能在之前的基础上继续迭代)。然后迭代次数怎么选呢?机器学习里很常用的迭代停止指标是看验证集的损失是否到达峰值,认为这个时候模型开始过拟合了。按照这个方法,我们可以从训练语料中分出一个验证集看损失函数的变化。但是实验中我们发现,这种策略并不好。主要原因就是,训练词向量的目标是,尽可能精确地预测目标词,这一目标和实际任务并不一致。所以更好的方法是,直接拿实际任务的验证集来做终止条件。如果实际任务做起来很慢(比如 NER 任务的开源实现大概做一次要两小时),文章还给了一种参考的方法,随便挑一个任务当验证集用,一般都比损失函数靠谱。
  词向量的维度则只有一些实验结果。做词向量语义分析任务的时候,一般维度越大效果越好。做具体 NLP 任务(用作特征、用作神经网络初始化)的时候,50 维之后效果提升就比较少了。这部分的结果很依赖于具体任务的实现,或许用上了更先进的神经网络优化方法,词向量作为初始值带来的影响又会有新的结论。

—————-枯燥结束的分割线—————-

  完全公平以及全面的比较是很难做到的,我们也在尽可能尝试逼近这个目标,希望这些结论会有用。请批评指正。当然,也非常非常欢迎引用~~~~~

97 评论

  1. 谢很贴心的附上中文导读,一口气拜读完。不能更赞同语料对词向量的影响。自向量化表示被广泛应用以来,横向评比就不再有公平性。之前在基于word2vec的paragraph2vec上做20类别的聚类任务,调参过程ACC可以10%变化到70%不得说调参也很可怕。

      1. 趋势是有的,小语料的时候LBL一次都没win,大的时候win的变多。不过这个确实就是猜测,现在是用may,可能换种表达会好点。

          1. 30、50次。最好还是用任务的验证集来测试。随便挑个30次,效果也不会太差,一般90%的效果还是有的。

  2. “主要原因就是,训练词向量的目标是,尽可能精确地预测目标词,这一目标和实际任务并不一致。所以更好的方法是,直接拿实际任务的验证集来做终止条件。”
    想问一下,什么是直接拿实际任务做验证集。比如我要做词性标注,那就在训练词向量时把输出层改成词性标注对应的吗,那神经网络的目标函数不就变了吗?
    本人目前新人一个,请指教

      1. 如果我的词性标注任务也用神经网络,没训练过的,那咋办? 再者每迭代一次都测试一下别的任务,这成本有点大吧

          1. 再问一下,训练词向量的维度以及网络优化方向对向量性能,我这里主要指对神经网络初始值优化方面有什么影响。训练词向量时如果有层级softmax或者打分,有没有优劣之分?博主做这方面研究时是用matlab吗,还是java, python之类的?谢了

  3. 莱神,请问您“拿词向量作为神经网络的初始值”是指作为神经网络节点的初始值吗?这个地方不太理解。。每个词向量应该是仅表示一个词的,直接用任意一个词的这个向量作为隐层的初始值吗?能否指点下,或者推荐个相关文章。感谢!

  4. 另外,关于这个文章有一些疑问,在Table 1中提到 skip-gram 是根据 c predicts w, 难道不应该反过来吗?后文还有一句话,skip-gram models uses one of the context words as the presentation of the context,这个怎么要怎么理解呢?
    感谢你的解答!

    1. 其实模型是对称的,哪个预测哪个都是对的。比如一个序列1 2 3。
      1预测2
      1预测3
      2预测1
      2预测3
      3预测1
      3预测2
      既然每个词都去预测了周围的另一个词,把谁看成c,把谁看成w,都是一样的。

  5. 你好,我最近在关注word2vec,读了您的文章,有很多不明白的地方,想请教你一下,不知道表4中的百分值是如何算出来的,有公式吗?由于我刚接触这方面,是个小白,还望大神指点,谢谢!

  6. state of the art 不是一个形容词么?意思是“先进”。 Bengio当初只是用这个来形容它那个东西不是直接那么命名了吧。

  7. 您好!菜鸟一枚有个小问题请教一下~
    我看word2vec理论的时候也看到说词序是无所谓的,但是在实践时,我发现词序不同,训练出的模型效果非常不一样,词序正确时是要好很多的。请问这是为什么呢??

      1. 博主好,我对您提到的word2vec的方法没有使用词序,不是很理解。是因为 对于CBOW,p(c|w),这里c的处理是加和而不是 像 A Neural Probabilistic Language Model 这篇论文一样拼接起来么? 对于skip-gram,直接就p(w|c)了,也没什么词序可言。 但我不是很理解为什么将词序去掉就加速了呢? 谢谢!

        1. 就是和你理解的一样。其实词序是有部分保留的,毕竟更远的词不会被算进来。但是附近的几个词的先后顺序,在word2vec里没法体现出。

  8. 这位老师,您好,请问你可以给我一个您们这篇论文《Recurrent Convolutional Neural Networks for Text Classification》的代码吗?如果可以不胜感激,就发我邮箱,谢谢

        1. 老师您好,请问你可以给我一个您们这篇论文《Recurrent Convolutional Neural Networks for Text Classification》的代码吗?如果可以不胜感激,就发我邮箱(1193144641@qq.com),谢谢

    1. 您好,请问你可以给我一个您们这篇论文《Recurrent Convolutional Neural Networks for Text Classification》的代码吗?如果可以不胜感激,就发我邮箱,谢谢

        1. 老师您好,能不能给我发下您们这篇论文《Recurrent Convolutional Neural Networks for Text Classification》的代码?我的邮箱1512568691@qq.com 谢谢老师

  9. 您好,最近在研究RNN的分类使用,我也想研究一下您的《Recurrent Convolutional Neural Networks for Text Classification》的代码,能提供一下吗?谢谢。

  10. 请教楼主一个问题,有没有试过对embedding用l2 regularization,效果怎样?几乎没看到过有人讨论word embedding的overfitting问题,楼主论文中提到了如果训练太久会overfitting,说明这个问题还是存在的,为什么没有人用l2等regularization方法解决这个问题呢?还是因为加l2会导致其他task的性能下降?

    1. 我自己没尝试过,可以尝试。只是我个人觉得加这个限制没什么用,因为看现有的词向量,没有出现参数特别大的,实践上怎么样还不知道。
      我觉得论文里面发现的overfitting主要是因为训练目标和实际任务不一致导致的。

      1. 博主,这个链接打不开呀?我还想请教博主一个问题,用Wordvec训练的话是找一个与我们的实验数据相似的语料去训练,然后通过查询训练好的词向量来初始化我们的实验数据呢还是直接用Wordvec将我们的实验语料生成向量的表征形式呢?

  11. 老师,您好,想研究一下您的《Recurrent Convolutional Neural Networks for Text Classification》的代码,方便的话可以提供下吗

  12. 非常有意思的文章!

    请问楼主对vocabulary size对performance的影响有做分析吗?vocabulary size过大会可能会导致引入过多noisy long-tail words,也会影响效果。

    1. 这篇文章没有分析。我一般定vocabulary siz的方法是,保证vocabulary里面的词在语料中出现的次数大于几十次。yoav建议是100次。

  13. 博主你好,我最近在研究CNN和RNN在文本分类中的应用,看了您的论文《Recurrent Convolutional Neural Networks for Text Classification》,对于第一个left context和最后一个right context的初始化、参数的计算过程这些细节的地方不太明白,能否提供代码学习下?谢谢!

  14. 老师,您好,读您的博客受益匪浅,也想研究一下您的《Recurrent Convolutional Neural Networks for Text Classification》的代码,方便的话可以提供下吗
    邮箱:2776131745@qq.com

  15. 老师您好,请问你可以给我一个您们这篇论文《Recurrent Convolutional Neural Networks for Text Classification》的代码吗?如果可以不胜感激,就发我邮箱(1193144641@qq.com),谢谢

  16. 大神您好,看了您的文章和博士论文,对我有很大启发,请问方便提供一下《Recurrent Convolutional Neural Networks for Text Classification》的代码吗,感激不尽!

  17. 老师您好,刚刚读了您的《Recurrent Convolutional Neural Networks for Text Classification》的论文,对里面CNN部分的实现很感兴趣,想问一下代码可以提供一份吗?如有打扰万分抱歉:)

  18. 你好,最近在做这方面的研究,请问能不能把你的代码发给我下,顺便把你的QQ号也发我下,交流交流,谢谢了~

  19. 您好,请问你可以给我一个您们这篇论文《Recurrent Convolutional Neural Networks for Text Classification》的代码吗?如果可以不胜感激,就发我邮箱,谢谢

  20. 博主您好,tensorflow官方教程(https://www.tensorflow.org/versions/r0.11/tutorials/word2vec/index.html#vector-representations-of-words)中一段描述:
    CBOW smoothes over a lot of the distributional information (by treating an entire context as one observation). For the most part, this turns out to be a useful thing for smaller datasets. However, skip-gram treats each context-target pair as a new observation, and this tends to do better when we have larger datasets.
    也就是说语料大的时候用skip-gram较好,和博主说的相反,这个需要如何理解呢?

    1. 其实我觉得“by treating an entire context as one observation”里面的“entire context”变化数量比context-target pair更丰富,所以很难直接理解他逻辑。可能在某些场合里面skip-gram会在大语料下效果好,只是我的实验没有发现。
      话说没找到怎么联系文档的作者,好想直接问问他。

  21. 我自己做实验用的数据是500万+个平均长度为15的句子,得到的是CBOW的效果比skip-gram好,但是我不确定我这个语料算大吗

  22. For the skipgram, the direction of the prediction is simply inverted, i.e. now we try to predict P(citizens | X), P(of | X), etc. This turns out to learn finer-grained vectors when one trains over more data. The main reason is that the CBOW smooths over a lot of the distributional statistics by averaging over all context words while the skipgram does not. With little data, this “regularizing” effect of the CBOW turns out to be helpful, but since data is the ultimate regularizer the skipgram is able to extract more information when more data is available.
    (https://www.quora.com/What-are-the-main-differences-between-CBOW-and-skip-gram-operationally-and-empirically-speaking)
    跟你说的(语料库小用skip-gram,大用cbow)恰好相反。

  23. 拜读。
    读到”实验中最意外的结果就是,语料对词向量的影响比模型的影响要重要得多得多得多(重要的事说三遍)。本来我只想固定一个语料,公平比较模型,结果却发现语料比模型重要(抱歉,是四遍)“
    时,我就在想,神经元网络的本质应该不单单是抽象,然后抛弃原始数据,而是把原始数据特征以一种我们没法理解的方式储存起来。所以语料是无损的信息,而模型是经过抽象和压缩后的有损信息。

    不知道这么想对不对,还在学习搭tensorflow 的基础框架,完全是萌新。

    1. 能把原始数据存下来肯定是最无损的,不过模型也是有意义的,因为语言是无法穷尽的,如果模型能学到通用的抽象泛化,就能做预测了。

  24. 你好,我在处理维基百科英文语料的时候。使用Wikipedia Extractor还有51nlp上的process_wiki.py代码抽取enwiki-latest-pages-articles.xml.bz2 时,抽取到一部分就报错了,我尝试在谷歌上搜索到一个回答是下载文件破损,于是我又重新下载了一次,并且核对了文件大小,但还是抽取到几百M的时候报错,接下来我有下载了维基百科英文3月20,3月01等后面几个版本,最成功的一次大概是抽取到10.8G的时候报错~~想请教一下来博士当时有没有遇到这种情况,还有我接下来改怎么做~~

  25. 老师您好,我也想读一下您的《Recurrent Convolutional Neural Networks for Text Classification》代码,希望老师可以发我一份。谢谢您!

  26. 博主你好,你在评价词向量质量以ws作为评价指标时,其中使用所有标注者打分的平均值作为参考得分 X,以
    词对的两个词向量的余弦距离作为模型得到的相关性得分 Y ,并衡量这两组数值之间的皮尔逊相关系数。两个词对的余弦距离的值应该是介于0到1之间的,二标注者评分值是0-10之间的,从code里面查看我没有发现进行归一化了,我想问这里应该时需要使用归一化才能计算它们之间的p皮尔森相关系数吧?

  27. 前辈您好,阅读了您的文章以后感到学习到挺多的。希望老师您能指导一下还可以从哪个点做一点小小改动以帮助完成一篇shuoshi paper

  28. I really appreciate your great works. I tried to run the evaluation ‘avg’, but failed to have the message “OSError: [Errno 2] No such file or directory: ‘vec_ivlblskip'”. I didn’t find any model directory in the github page. Would you please help me to overcome this issue? or would you please send me the total working code at muhammedazamkhan@gmail.com? Thank you very much.

发表评论

电子邮件地址不会被公开。 必填项已用*标注