原博:http://blog.csdn.net/yelbosh/article/details/49721569
Google的word2vec官网:https://code.google.com/p/word2vec/
下载下来的Demo源码文件共有如下几个:
word2vec – Revision 41: /trunk
…
LICENSE //Apache LICENSE
README.txt //工具使用说明
compute-accuracy.c
demo-analogy.sh //
demo-classes.sh //词聚类的示例脚本
demo-phrase-accuracy.sh
demo-phrases.sh //
demo-train-big-model-v1.sh
demo-word-accuracy.sh
demo-word.sh
distance.c
makefile
questions-phrases.txt
questions-words.txt
word-analogy.c
word2phrase.c
word2vec.c
【快速入门】:1. 从http://word2vec.googlecode.com/svn/trunk/ 下载所有相关代码(所有的文件如上);
2. 运行make编译word2vec工具:Makefile的编译代码在makefile.txt文件中,先改名makefile.txt 为Makefile,然后在当前目录下执行make进行编译,生成可执行文件(编译过程中报出很出Warning,暂且不管);
3. 运行示例脚本:./demo-word.sh 和 ./demo-phrases.sh:看一下./demo-word.sh的内容,大致执行了3步操作
a). 从http://mattmahoney.net/dc/text8.zip 下载了一个文件text8 ( 一个解压后不到100M的txt文件,可自己下载并解压放到同级目录下),
b). 执行word2vec生成词向量到 vectors.bin文件中,(速度比较快,几分钟的事情)
2.将分好词的训练语料进行训练,假定我语料名称为test.txt且在word2vec目录中。输入命令:
./word2vec -train text8 -output vectors.bin -cbow 0 -size 48 -window 5 -negative 0 -hs 1 -sample 1e-4 -threads 20 -binary 1 -iter 100
以上命令 -train text8 表示的是输入文件是text8,-output vectors.bin 输出文件是vectors.bin,-cbow 0表示不使用cbow模型,默认为Skip-Gram模型。-size 48 每个单词的向量维度是48,-window 5 训练的窗口大小为5就是考虑一个词前五个和后五个词语(实际代码中还有一个随机选窗口的过程,窗口大小小于等于5)。-negative 0 -hs 1不使用NEG方法,使用HS方法。-sampe指的是采样的阈值,如果一个词语在训练样本中出现的频率越大,那么就越会被采样。-binary为1指的是结果二进制存储,为0是普通存储(普通存储的时候是可以打开看到词语和对应的向量的)除了以上命令中的参数,word2vec还有几个参数对我们比较有用比如-alpha设置学习速率,默认的为0.025. –min-count设置最低频率,默认是5,如果一个词语在文档中出现的次数小于5,那么就会丢弃。-classes设置聚类个数,看了一下源码用的是k-means聚类的方法。要注意-threads 20 线程数也会对结果产生影响。
注意:–min-count设置最低频率,默认是5,进行参数传递无效,我们可能是因为参数名中有-,唉我们只好在程序word2vec.c中将min-count初始化为1了。
· 架构:skip-gram(慢、对罕见字有利)vs CBOW(快)
· 训练算法:分层softmax(对罕见字有利)vs 负采样(对常见词和低纬向量有利)
· 欠采样频繁词:可以提高结果的准确性和速度(适用范围1e-3到1e-5)
· 文本(window)大小:skip-gram通常在10附近,CBOW通常在5附近
[root@localhost /home/jacoxu/word2vec]$./demo-word.sh
make: Nothing to be done for `all’.
Starting training using file text8
Vocab size: 71291
Words in train file: 16718843
Alpha: 0.000560 Progress: 98.88% Words/thread/sec: -117.11k
c). 执行./distance vectors.bin可以进入一个计算word相似度的demo中去,如下:
========中断========
52 if (ch == ‘\n’) {
53 strcpy(word, (char *)””);
148 // Sort the vocabulary and keep at the first position
149 qsort(&vocab[1], vocab_size – 1, sizeof(struct vocab_word), VocabCompare);
—-
看代码,应该是\n这个词,而且特意排在第一位了
====================
对于训练出来的模型进行操作,我推荐大家使用http://blog.csdn.net/zhaoxinfan/article/details/11640573这个java版本的模型读取类,比较方便。可以参照:http://blog.csdn.net/jj12345jj198999/article/details/11069485
Enter word or sentence (EXIT to break): china
Word: china Position in vocabulary: 486
Word Cosine distance (找到了很多和china共现度很高的词汇,可以得到认可)
————————————————————————
taiwan 0.656181
japan 0.633499
tibet 0.607813
manchuria 0.581230
hainan 0.561931
xiamen 0.555860
chongqing 0.550099
jiang 0.549195
chinese 0.548320
liao 0.548220
…
Enter word or sentence (EXIT to break): hongkong
Word: hongkong Position in vocabulary: 24623
Word Cosine distance(感觉效果很糟糕,有些不知所云,认可度很低,主要还是因为语料太少,覆盖面窄)
————————————————————————
jardines 0.708792
matheson 0.659444
jardine 0.611295
shareholding 0.489012
company 0.431918
kowloon 0.417640
firm 0.415780
venture 0.415077
plc 0.409350
shanghai 0.404716
…
然后看一下./demo-phrases.sh的内容,也大致执行了3步操作:
a). 从http://www.statmt.org/wmt14/training-monolingual-news-crawl/news.2012.en.shuffled.gz 下载了一个文件news.2012.en.shuffled.gz ( 一个解压到1.7G的txt文件,可自己下载并解压放到同级目录下);
b). 将文件中的内容拆分成 phrases,然后执行./word2vec生成短语向量到 vectors-phrase.bin文件中(数据量大,速度慢,将近半个小时),如下:
[root@localhost /home/jacoxu/word2vec]$ bash demo-phrases.sh (总耗时75分钟)
make: Nothing to be done for `all’.
Starting training using file news.2012.en.shuffled-norm0
Words processed: 296900K Vocab size: 33198K
Vocab size (unigrams + bigrams): 18838711
Words in train file: 296901342
Words written: 296900K
real 11m1.465s
user 10m47.888s
sys 0m8.317s
Starting training using file news.2012.en.shuffled-norm0-phrase0
Words processed: 280500K Vocab size: 38761K
Vocab size (unigrams + bigrams): 21728781
Words in train file: 280513979
Words written: 280500K
real 10m43.277s
user 10m29.983s
sys 0m8.137s
Starting training using file news.2012.en.shuffled-norm1-phrase1
Vocab size: 681320
Words in train file: 283545447
Alpha: 0.000005 Progress: 100.00% Words/thread/sec: 83.67k
real 49m3.925s
user 847m21.369s
sys 1m11.140s
c). 执行./distance vectors-phrase.bin 可以进入一个计算word相似度的demo中去,如下:
Enter word or sentence (EXIT to break): great_wall
Word: great_wall Position in vocabulary: 36052
Word Cosine distance (确实找到一些极为相关的词汇)
————————————————————————
mutianyu 0.588232
terra_cotta_warriors 0.541900
forbidden_city 0.527797
changsha 0.520975
based_koryo_tours 0.510810
three_gorges 0.509765
world’s_tallest 0.501899
dajie 0.500128
ming_dynasty 0.496112
qin_shihuang 0.486954
…
Enter word or sentence (EXIT to break): hong_kong
Word: hong_kong Position in vocabulary: 2322
Word Cosine distance (并没有任何体现Hong Kong本土的词汇,仍是语料的问题)
————————————————————————
singapore 0.755051
mainland_china 0.739481
shanghai 0.732764
hong_kong’s 0.727834
mainland_chinese 0.652696
singapore’s 0.636082
keith_bradsher_contributed_reporting 0.626221
hang_seng_index_fell 0.621854
chinese 0.617985
taipei 0.609921
…
【其他】:Java版本Word2Vector
词向量的训练最经典的有 3 个工作,C&W 2008、M&H 2008、Mikolov 2010,看看其他几个版本的Word Embedding:
(以下大部分内容摘自Zhao老板的学生licstar)
1. 【C&W 的 SENNA – 2008】
■ 训练语料及规模:English Wikipedia + Reuters RCV1 共 631M + 221M 词;
■ 词向量:130000 词,50 维;
■ 特点:不区分大小写,经过有监督修正,训练了7周;
■ 资源:测试代码、词向量 [链接]
Ronan Collobert 和 Jason Weston 在 2008 年的 ICML 上发表的《A Unified Architecture for Natural Language Processing: Deep Neural Networks with Multitask Learning》里面首次介绍了他们提出的词向量的计算方法,他们还把论文所写的系统开源了,叫做 SENNA,3500 多行纯 C 代码也是写得非常清晰。C&W 这篇论文主要目的并不是在于生成一份好的词向量,甚至不想训练语言模型,而是要用这份词向量去完成 NLP 里面的各种任务,比如词性标注、命名实体识别、短语识别、语义角色标注等等。
2. 【M&H 的 HLBL – 2007】
Andriy Mnih 和 Geoffrey Hinton 在 2007 年和 2008 年各发表了一篇关于训练语言模型和词向量的文章。2007 年发表在 ICML 上的《Three new graphical models for statistical language modelling》表明了 Hinton 将 Deep Learning 战场扩展到 NLP 领域的决心。2008 年发表在 NIPS 上的《A scalable hierarchical distributed language model》则提出了一种层级的思想替换了 Bengio 2003 方法中最后隐藏层到输出层最花时间的矩阵乘法,在保证效果的基础上,同时也提升了速度。2008 年 NIPS 的这篇论文,介绍的是“hierarchical log-bilinear”模型,很多论文中都把它称作简称“HLBL”。
3. 【Mikolov 的 RNNLM – 2010】
■ 训练语料及规模:Broadcast news;
■ 词向量:82390 词,80、640、1600 维;
■ 特点:不区分大小写;训练了若干天;
■ 资源:训练、测试代码、词向量 [链接]
Bengio 2003 在论文里提到一句,可以使用一些方法降低参数个数,比如用循环神经网络。Mikolov 就抓住了这个坑,从此与循环神经网络结下了不解之缘。他最早用循环神经网络做语言模型是在 INTERSPEECH 2010 上发表的《Recurrent neural network based language model》里。Recurrent neural network 是循环神经网络,简称 RNN,还有个 Recursive neural networks 是递归神经网络(Richard Socher 借此发了一大堆论文),也简称 RNN。看到的时候需要注意区分一下。不过到目前为止,RNNLM 只表示循环神经网络做的语言模型,还没有歧义。
在之后的几年中,Mikolov 在一直在RNNLM 上做各种改进,有速度上的,也有准确率上的。现在想了解 RNNLM,看他的博士论文《Statistical Language Models based on Neural Networks》肯定是最好的选择。
4. 【Huang 的语义强化 – 2012】
■ 训练语料及规模:English Wikipedia;
■ 词向量:100232 词,50 维;
■ 特点:不区分大小写,最高频的6000词,每词有10种表示;
■ 资源:训练、测试代码、词向量 [链接]
与前几位大牛的工作不同,Eric H. Huang 的工作是在 C&W 的基础上改进而成的,并非自成一派从头做起。他这篇发表在 ACL 2012 上的《Improving Word Representations via Global Context and Multiple Word Prototypes》试图通过对模型的改进,使得词向量富含更丰富的语义信息。他在文中提出了两个主要创新来完成这一目标:(其实从论文标题就能看出来)第一个创新是使用全文信息辅助已有的局部信息,第二个创新是使用多个词向量来表示多义词。
Huang 认为 C&W 的工作只利用了“局部上下文(Local Context)”。C&W 在训练词向量的时候,只使用了上下文各 5 个词,算上自己总共有 11 个词的信息,这些局部的信息还不能充分挖掘出中间词的语义信息。Huang 直接使用 C&W 的网络结构计算出一个得分,作为“局部得分”。
然后 Huang 提出了一个“全局信息”,这有点类似传统的词袋子模型。词袋子模型是把文章中所有词的 One-hot Representation 加起来,形成一个向量(就像把词全都扔进一个袋子里),用来表示文章。Huang 的全局模型是将文章中所有词的词向量求个加权平均(权重是词的 idf),作为文章的语义。他把文章的语义向量和当前词的词向量拼接起来,形成一个两倍长度的向量作为输入,之后还是用 C&W 的网络结构算出一个打分。
有了 C&W 方法的得到的“局部得分”,再加上在 C&W 方法基础上改造得到的“全局得分”,Huang 直接把两个得分相加,作为最终得分。最终得分使用 C&W 提出的 pair-wise 目标函数来优化。
加了这个全局信息有什么用处呢?Huang 在实验中发现,他的模型能更好地捕捉词的语义信息。比如 C&W 的模型中,与 markets 最相近的词为 firms、industries;而 Huang 的模型得到的结果是 market、firms。很明显,C&W 的方法由于只考虑了临近词的信息,最后的结果是词法特征最相近的词排在了前面(都是复数形式)。不过我觉得这个可能是英语才有的现象,中文没有词形变化,如果在中文中做同样的实验还不知道会有什么效果。
Huang 论文的第二个贡献是将多义词用多个词向量来表示。Bengio 2003 在最后提过这是一个重要的问题,不过当时他还在想办法解决,现在 Huang 给出了一种思路。
将每个词的上下文各 5 个词拿出来,对这 10 个词的词向量做加权平均(同样使用 idf 作为权重)。对所有得到的上下文向量做 k-means 聚类,根据聚类结果给每个词打上标签(不同类中的同一个词,当作不同的词处理),最后重新训练词向量。
当然这个实验的效果也是很不错的,最后 star 的某一个表示最接近的词是 movie、film;另一个表示最接近的词是 galaxy、planet。
5. 【Turian 对比试验 – 2010】
优化C&W代码并重跑试验
■ 训练语料及规模:Reuters RCV1 63M 词;
■ 词向量:268810 词 25、50、100、200 维;
■ 特点:区分大小写,训练了若干周;
■ 资源:训练代码、词向量 [链接]
由M帮忙重跑M&H
■ 训练语料及规模:Reuters RCV1;
■ 词向量:246122 词 50、100 维;
■ 特点:区分大小写,用GPU训练了7天;
■ 资源:训练代码、词向量 [链接]
问题?主页上提供了 两份 词向量,一份是 scaled,一份是unscaled,scaled的作用是什么?这个Scale貌似是全局的,而非单个向量的。
README.text中是这么解释的:
embeddings-scaled.*.txt.gz
Embeddings scaled by 0.1/stddev(embeddings), as described in the ACL 2010 paper.
These are the embeddings you should use by default, if you just want word features.
The first column is the word, the rest of the columns are the dimensions of the embedding.
也就是说通过stddev进行了一个全局的样本标准偏差进行缩放;
Turian 的工作前面只是提了一下,他在做 C&W 向量与 H&M 向量的对比实验时,自己按照论文重新实现了一遍他们的方法,并公布了词向量。后来 C&W 在主页上强调了一下:尽管很多论文把 Turian 实现的结果叫做 C&W 向量,但是与我发布的词向量是不同的,我这个在更大的语料上训练,还花了两个月时间呢!
Turian 公布的 M&H 向量是直接请 Andriy Mnih 在 Turian 做好的语料上运行了一下 HLBL,所以没有代码公布。同时 Turian 自己实现了一份 LBL模型,但是没有公布训练出来的词向量。(这是根据他主页上描述推测的结果,从 Turian 的论文中看,他应该是实现了 HLBL 算法并且算出词向量的。)
RCV1 的词数两篇文章中所写的数据差距较大,还不知道是什么原因。
Turian 发表在 ACL 2010 上的实验对比了 C&W 向量与 M&H 向量用作辅助特征时的效果。在短语识别和命名实体识别两个任务中,C&W 向量的效果都有略微的优势。同时他也发现,如果将这两种向量融合起来,会有更好的效果。除了这两种词向量,Turian 还使用 Brown Cluster 作为辅助特征做了对比,效果最好的其实是 Brown Cluster,不过这个已经超出本文的范围了。
【值得一读】:
1. What are the continuous bag of words and skip-gram architectures
2. Hierarchical Softmax & Negative Sampling
3. word2vec 中的数学原理详解
4. Deep Learning in NLP (一)词向量和语言模型:http://licstar.net/archives/328
【问题语料训练实例】
1. 搜集语料
StackOverflow语料下载train.zip https://www.kaggle.com/c/predict-closed-questions-on-stack-overflow/ 进行处理,得到content内容和title标题作为训练语料
2. 利用word2vec进行训练,采用和官网提供的300维Vector同样的训练模型:
-cbow 1 -size 300 -window 5 -negative 3 -hs 0 -sample 1e-5 -threads 12 -binary 1 -iter 15
(注:默认的低频下限是5,由于当前版本(word2vec42)程序有bug,原因不太清楚,如果初始化失败,则到word2vec.c文件中修改此值)
475630606个words, vocab 大小为1598580,大概花费25分钟。
运行结果并测试效果如下:
- [root@linux-237 word2vec42]# bash demo-word.sh
- make: Nothing to be done for `all’.
- Starting training using file stackText.txt
- Vocab size: 1598580
- Words in train file: 475630606
- Alpha: 0.000263 Progress: 99.47% Words/thread/sec: 541.23k
- real 25m39.774s
- user 221m57.108s
- sys 0m49.199s
- Enter word or sentence (EXIT to break): java
- Word: java Position in vocabulary: 454
- Word Cosine distance
- ————————————————————————
- Java 0.804742
- java, 0.780371
- java. 0.775374
- JAVA 0.743753
- Java. 0.683836
- swing 0.674023
- android 0.672503
- c++ 0.668149
- c# 0.644594
- python 0.643520
- eclipse 0.643359
- Java, 0.637573
- java? 0.630209
- jar 0.628616
- groovy 0.627132
- scala 0.611233
- servlet 0.610064
- applet 0.608627
- php 0.608549
- i 0.600868
- my 0.599664
- jsp 0.598296
- ruby 0.597236
- netbeans 0.595057
- a 0.595011
- write 0.594350
- program 0.593679
- jdk 0.593030
- j2me 0.587537
- which 0.585925
- to 0.585683
- using 0.580617
- that 0.579790
- written 0.579572
- some 0.579534
- android, 0.577219
- and 0.575742
- .net 0.575061
- web 0.574278
- linux 0.573493
- Enter word or sentence (EXIT to break): html
- Word: html Position in vocabulary: 394
- Word Cosine distance
- ————————————————————————
- HTML 0.853783
- html. 0.836931
- html, 0.795768
- javascript 0.763503
- HTML. 0.721012
- js 0.715835
- webpage 0.711215
- HTML, 0.700154
- content 0.694945
- markup 0.691843
- Html 0.686390
- css 0.683201
- tags 0.676316
- javascript, 0.676179
- xhtml 0.674844
- javascript. 0.674052
- php 0.673596
- text 0.673089
- page 0.663661
- xml 0.662498
- iframe 0.661740
- jquery 0.652209
- tag 0.651575
- webpage, 0.647792
- content, 0.644945
- .html 0.641437
- aspx 0.638099
- ajax 0.637875
- html? 0.633876
- jsp 0.631024
- tags, 0.624686
- textarea 0.624658
- webpage. 0.624080
- pdf 0.622019
- page, 0.620723
- contents 0.617092
- JS 0.615214
- text, 0.613630
- form 0.613238
- css. 0.612103
- Enter word or sentence (EXIT to break): android
- Word: android Position in vocabulary: 495
- Word Cosine distance
- ————————————————————————
- Android 0.857668
- android. 0.814769
- android, 0.810972
- iphone 0.744005
- blackberry 0.719089
- Android. 0.718010
- androids 0.693840
- Android, 0.687129
- emulator 0.680624
- java 0.672503
- android? 0.664975
- phone. 0.661444
- Blackberry 0.658390
- andriod 0.653750
- android’s 0.648015
- phonegap 0.641884
- emulator. 0.640713
- iPhone 0.639118
- ios 0.639108
- tablet 0.636023
- Iphone 0.635636
- j2me 0.632937
- phone 0.630827
- mobile 0.624277
- device 0.621280
- apk 0.619061
- phone, 0.611067
- ICS 0.610646
- adroid 0.606088
- emulator, 0.604733
- activity 0.603200
- 2.2 0.602148
- eclipse 0.599507
- Honeycomb 0.597581
- device. 0.597449
- IOS 0.597157
- honeycomb 0.596399
- iphone. 0.595373
- sdk 0.592870
- iOS 0.591931
参考:https://groups.google.com/forum/#!topic/word2vec-toolkit/lxbl_MB29Ic Tomas Mikolov 用了9个小时进行训练WIKI数据。
./word2vec -train train100B.txt -read-vocab voc -output vectors.bin -cbow 1 -size 300 -window 5 -negative 3 -hs 0 -sample 1e-5 -threads 12 -binary 1 -min-count 10
除了上面的语料,Tomas Mikolov,在他的word2vec主页上还提供了WIKI语料的链接,以及XML文件预处理的批文件。
使用方式为:perl wikifil.pl enwik9 > text (下载地址:http://mattmahoney.net/dc/textdata.html)