word2vec 入门基础
基本概念
word2vec是Google在2013年开源的一个工具,核心思想是将词表征映射为对应的实数向量。
目前采用的模型有以下两种
- CBOW(Continuous Bag-Of-Words,即连续的词袋模型)
- Skip-Gram
项目链接:https://code.google.com/archive/p/word2vec
背景知识
词向量
词向量就是用来将语言中的词进行数学化的一种方式,顾名思义,词向量就是把一个词表示成一个向量。这样做的初衷就是机器只认识0 1 符号,换句话说,在自然语言处理中,要想让机器识别语言,就需要将自然语言抽象表示成可被机器理解的方式。所以,词向量是自然语言到机器语言的转换。
词向量有一下两种
-
One-hot Representation
向量的长度为词典的大小,向量的分量只有一个 1,其他全为 0, 1 的位置对应该词在词典中的位置,例如
“话筒”表示为 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 …]
“麦克”表示为 [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 …]
优点: 如果使用稀疏方式存储,非常简洁,实现时就可以用0,1,2,3,…来表示词语进行计算,这样“话筒”就为3,“麦克”为8.
缺点:
- 容易受维数灾难的困扰,尤其是将其用于 Deep Learning 的一些算法时;
- 任何两个词都是孤立的,存在语义鸿沟词(任意两个词之间都是孤立的,不能体现词和词之间的关系)。
-
Distributional Representation
最早是 Hinton 于 1986 年提出的,可以克服 one-hot representation的缺点。解决“词汇鸿沟”问题,可以通过计算向量之间的距离(欧式距离、余弦距离等)来体现词与词的相似性。其基本想法是直接用一个普通的向量表示一个词,这种向量一般长成这个样子:[0.792, −0.177, −0.107, 0.109, −0.542, …],常见维度50或100。
优点:解决“词汇鸿沟”问题;
缺点:训练有难度。没有直接的模型可训练得到。所以采用通过训练语言模型的同时,得到词向量 。
当然一个词怎么表示成这么样的一个向量是要经过一番训练的,训练方法较多,word2vec是其中一种。值得注意的是,每个词在不同的语料库和不同的训练方法下,得到的词向量可能是不一样的。
词向量在机器翻译领域的一个应用就是google的TomasMikolov团队开发了一种词典和术语表的自动生成技术,该技术通过向量空间,把一种语言转变成另一种语言,实验中对英语和西班牙语间的翻译准确率高达90%。
论文http://arxiv.org/pdf/1309.4168.pdf在介绍算法工作原理的时候举了一个例子:考虑英语和西班牙语两种语言,通过训练分别得到它们对应的词向量空间E 和S 。从英语中取出五个单词one,two,three,four,five,设其在E 中对应的词向量分别为 v1,v2,v3,v4,v5,为方便作图,利用主成分分析(PCA)降维,得到相应的二维向量 u1,u2,u3,u4,u5,在二维平面上将这五个点描出来,如下图左图所示。类似地,在西班牙语中取出(与 one,two,three,four,five 对应的) uno,dos,tres,cuatro,cinco,设其在S 中对应的词向量分别为 s1,s2,s3,s4,s5,用 PCA 降维后的二维向量分别为 t1,t2,t3,t4,t5,将它们在二维平面上描出来(可能还需作适当的旋转),如下图右图所示:
观察左、右两幅图,容易发现:五个词在两个向量空间中的相对位置差不多,这说明两种不同语言对应向量空间的结构之间具有相似性,从而进一步说明了在词向量空间中利用距离刻画词之间相似性的合理性。
语言模型
语言模型其实就是看一句话是不是正常人说出来的。意义在于机器翻译、语音识别得到若干候选之后,可以利用语言模型挑一个尽量靠谱的结果。在NLP的其它任务里也都能用到。用数学符号描述为:给定一个字符串
上面概率公式的意义为:第一次词确定后,看后面的词在前面次出现的情况下出现的概率。
例如,有个句子“大家喜欢吃苹果”,一共四个词: 大家,喜欢,吃,苹果
- p(大家)表示“大家”这个词在语料库里面出现的概率;
- p(喜欢|大家)表示“喜欢”这个词出现在“大家”后面的概率;
- p(吃|大家,喜欢)表示“吃”这个词出现在“大家喜欢”后面的概率;
- p(苹果|大家,喜欢,吃)表示“苹果”这个词出现在“大家喜欢吃”后面的概率。
把这些概率连乘起来,得到的就是这句话平时出现的概率。
如果这个概率特别低,说明这句话不常出现,那么就不算是一句自然语言,因为在语料库里面很少出现。如果出现的概率高,就说明是一句自然语言。 为了表示简单,上面的公式用下面的方式表示:
其中,如果Contexti是空的话,就是它自己
现有模型有
- N-gram模型
- N-pos模型
- Bengio的NNLM
- C&W 的 SENNA
- M&H 的 HLBL
- Mikolov 的 RNNLM
- Huang 的语义强化
N-gram 模型
接下来说
可以想到的优化方法就是提前将
所以诞生了
我们给定一个词,然后猜测下一个词是什么。当我说“艳照门”这个词时,你想到的下一个词时什么?我想大家很有可能会想到“陈冠希”,基本上不会有人想到“陈志杰”吧。
上面的context都是这句话中这个词前面的所有词作为条件的概率,
一般来说, n取2或者3
假设词表中词的个数 |V| = 20,000 词,那么有下面的一些数据。
照图中的数据看去,取n=3是目前计算能力的上限了。在实践中用的最多的就是
如果一个词的出现仅依赖于它前面出现的一个词,那么我们就称之为
如果一个词的出现仅依赖于它前面出现的两个词,那么我们就称之为
那么我们怎么得到
下面我们用
- n不能取太大,取大了语料库经常不足,所以基本是用降级的方法
- 无法建模出词之间的相似度,就是有两个词经常出现在同一个context后面,但是模型是没法体现这个相似性的。
- 有些n元组(n个词的组合,跟顺序有关的)在语料库里面没有出现过,对应出来的条件概率就是0,这样一整句话的概率都是0了,这是不对的,解决的方法主要是两种:平滑法(基本上是分子分母都加一个数)和回退法(利用n-1的元组的概率去代替n元组的概率)
该博文主要是前段时间学习word2vec的一个总结,大部分都是网上资料,主要是做了个整理。算是做个备份,方便以后复习之类的。在此感谢前辈们的资料~~~
word2vec安装使用
安装
从http://word2vec.googlecode.com/svn/trunk/ 下载所有相关代码,下载下来之后是 .tar.gz文件,使用如下图中的解压缩命令解压: tar -xzvf word2vec-2014-10-29.tar.gz, 解压过程如图所示。
解压之后生成文件w2v,如下图:
cd到truck目录下,该目录下的文件如下图:
在当前目录下执行make进行编译,生成可执行文件。
编译之后的目录下的文件如下图:
使用
训练自带的text8
在http://mattmahoney.net/dc/text8.zip下载训练数据test8.zip。下载完成之后将该文件放在trunk目录下。此时可以vi demo word.sh查看下这个文件中的内容,其中的脚本如下:
因为已经编译和下载了text8数据集了,所以可以删除相应的代码(1,2,3,4行)
- make编译,
- wget http://mattmahoney.net/dc/text8.zip下载,
- gzip -d text8.gz -f解压,
只保留:
time ./word2vec -train text8 -output vectors.bin -cbow 1 -size 200 -window 8 -negative 0 -hs 1 -sample 1e-3 -threads 12 -binary 1 ./distance vectors.bin
运行这个名为demo-word.sh的文件就可以开始使用word2vec在数据集text8上进行训练得到词向量。
以上命令的参数作用如下:
- -train text8 表示的是输入文件是text8
- -output vectors.bin 输出文件是vectors.bin
- -cbow 1 表示使用cbow模型,默认为Skip-Gram模型
- -size 200 每个单词的向量维度是200
- -window 8 训练的窗口大小为8就是考虑一个词前八个和后八个词语(实际代码中还有一个随机选窗口的过程,窗口大小小于等于8)
- -negative 0 -hs 1不使用NEG方法,使用HS方法。
- -binary 1指的是结果二进制存储,为0是普通存储(普通存储的时候是可以打开看到词语和对应的向量的)
- -iter 15 迭代次数
训练的过程大概几分钟:
因为脚本demo-word.sh中最后一行命令是 ./distance vectors.bin,所以在词向量化完之后我们可以计算与给定词比较接近的词,例如这个时候我们输入
或者查看与
当然还可以使如下的命令来得到txt文件,这样我们就可以查看到每一个词的词向量
time ./word2vec -train text8 -output vectors.txt -cbow 1 -size 100 -windows 8 -negative 25 -hs 0 -sample 1e-4 -threads 20 -binary 0 -iter 15
查看text8中的词向量:(以下显示的是many,who,new,used的向量化结果)
此外,word2vec还有几个参数对我们比较有用比如:
- -alpha 设置学习速率,默认的为0.025.
- -min-count 设置最低频率,默认是5,如果一个词语在文档中出现的次数小于5,那么就会丢弃。
- -classes 100设置聚类个数为100,使用的方法是k-means。
-threads 20 线程数也会对结果产生影响。
架构:skip-gram(慢、对罕见字有利)vs CBOW(快)
- 训练算法:分层softmax(对罕见字有利)vs 负采样(对常见词和低纬向量有利)
- 欠采样频繁词:可以提高结果的准确性和速度(适用范围1e-3到1e-5)
- 文本(window)大小:skip-gram通常在10附近,CBOW通常在5附近
同样可以运行命令 ./demo-phrases.sh :查看该脚本内容,主要执行以下步骤:
- 从 http://www.statmt.org/wmt14/training-monolingual-news-crawl/news.2012.en.shuffled.gz 下载了一个文件news.2012.en.shuffled.gz ( 一个解压到1.7G的txt文件,可自己下载并解压放到同级目录下);
- 将文件中的内容拆分成 phrases,然后执行./word2vec生成短语向量到 vectors-phrase.bin文件中, 最后一行命令 ./distance vectors-phrase.bin ,计算word相似度
训练wiki_chinese_preprocessed.simplied.txt数据集
wiki_chinese_preprocessed.simplied.txt数据内容如下(已经分词):
对wiki_chinese_preprocessed.simplied.txt进行向量化,然后将结果聚为100类。每一个词的维度为100。
./word2vec -train wiki_chinese_preprocessed.simplied.txt -output wiki_chinese_classes.txt -cbow 0 -size 100 -window 5 -negative 0 -hs 1 -sample 1e-3 -threads 12 -classes 100
对聚类的结果按照类别排序.
sort wiki_chinese_classes.txt -k 2 -n > classes.sorted.txt