前两天怒刷微博,突然发现了刘知远老师分享的微博,顿时眼前一惊。原Po例如以下:
http://weibo.com/1464484735/BhbLD70wa
因为我眼下的研究方向是word2vec。暗自折服于它在word analogy task上狂暴吊炸天的能力,对于glove这样能够击败word2vec的大牛,也必定会产生好奇心。
于是便对它做了初步分析,便有了本文,希望能够抛砖引玉。期待很多其它人对这方面的研究。
因为本人学术水平不够,本文不会涉及glove详细实现的方法,不过介绍怎样使用官网代码,并利用python脚本,将glove训练好的model读取,(仿照word2vec)计算随意单词的最相似的TOP N个单词,并利用kmeans对单词进行聚类。用于与word2vec比較结果。
首先,先发出这个paper的homepage:
http://www.socher.org/index.php/Main/GloveGlobalVectorsForWordRepresentation
今天更新发现跳转到例如以下页面:
http://nlp.stanford.edu/projects/glove/
这里能够找到几个他们用wekipida训练好的model,只是我们一开是不须要关心这个,我们须要关心的是源码所在的位置,也就是:
http://nlp.stanford.edu/software/glove.tar.gz
下载好glove.tar.gz,基本就能够開始训练了。大家从它的后缀名就应该猜出来,它也是须要在linux下编译执行的程序。各位用windows的。仅仅能參考当初怎样用cygwin解决执行word2vec的方法了。(这也不会是本文重点,各位加油!)在linux下解压该文件:
tar -xzvf glove.tar.gz
进入glove文件夹下,首先先參考README.txt,里面主要介绍这个程序包括了四部分子程序,按步骤各自是vocab_count、cooccur、shuffle、glove。本人用拙劣的翻译技巧大概为各位介绍下每部分要做的事情。假设有介绍错误的。还望指出:
1.vocab_count:用于计算原文本的单词统计(生成vocab.txt,每一行为:单词 词频)
2.cooccur:用于统计词与词的共现。目測类似与word2vec的窗体内的随意两个词(生成的是cooccurrence.bin,二进制文件,呵呵)
3. shuffle:对于2中的共现结果又一次整理(一看到shuffle瞬间想到hadoop,生成的也是二进制文件cooccurrence.shuf.bin)
4.glove:glove算法的训练模型,会运用到之前生成的相关文件(1&3),终于会输出vectors.txt和vectors.bin(前者直接能够打开,下文主要针对它做研究。后者还是二进制文件)
上面已经介绍了这个程序的运行流程,以下就详细训练出这个vectors.txt。
首先二话不说。直接
make
编译程序,假设报错。那仅仅能呵呵了,自己研究下报错原因。多半可能是gcc版本号不正确,我用的是4.7.3。
假设编译通过了,你要注意的是,事实上大牛早就已经给你写好了运行程序。就是demo.sh,你须要做的就是简单的一步:
sh demo.sh
假设报错说权限不够,相信各位大牛一定知道怎样改动权限,我就是最暴力的:
chmod 777 glove/*
我在执行的时候报了:
demo.sh: 26: demo.sh: [[: not found
这种错误。为了解决这个错误,我打开了恐怖的demo.sh,发现它做的任务很easy。首先它自己一開始就make了(笔者上述的make操作略显多余),接下来去下那个text8(目測和word2vec是同一个东西),接下来定义了一系列常量,然后运行了四步操作。因为笔者对bash的不熟悉。笔者就暴力的把里面的全部的if都干掉了,训练部分代码变成例如以下这样:
./vocab_count -min-count $VOCAB_MIN_COUNT -verbose $VERBOSE < $CORPUS > $VOCAB_FILE ./cooccur -memory $MEMORY -vocab-file $VOCAB_FILE -verbose $VERBOSE -window-size $WINDOW_SIZE < $CORPUS > $COOCCURRENCE_FILE ./shuffle -memory $MEMORY -verbose $VERBOSE < $COOCCURRENCE_FILE > $COOCCURRENCE_SHUF_FILE ./glove -save-file $SAVE_FILE -threads $NUM_THREADS -input-file $COOCCURRENCE_SHUF_FILE -x-max $X_MAX -iter $MAX_ITER -vector-size $VECTOR_SIZE -binary $BINARY -vocab-file $VOCAB_FILE -verbose $VERBOSE octave -nodisplay -nodesktop -nojvm -nosplash < ./eval/read_and_evaluate.m 1>&2
各位不要笑我,训练出model先。最后运行sh demo.sh,成功生成vectors.txt。
(说句题外话,我们能够从glove的參数看得出来,人家也是支持多线程的。在text8语料库训练50维向量。我花了7分钟时间《i5 core+4g内存》,还没有来得及和word2vec对照时间。感觉比word2vec慢)可是还是会报错,详细错误就不显示。主要是由于这个demo.sh接下来调用自己在eval目录下写好的matlab代码来分析结果,无奈我Linux下没有安装matlab,我还自做聪明的把matlab改动成octave(见刚刚的第四行),但还是不行,就在这时,我得到张成老师的给力回复:
瞬间发现自己好傻,明明已经生成了vectors.txt。为啥还要用它的matlab代码调用,于是就有了例如以下的脚本文件:
https://github.com/eclipse-du/glove_py_model_load/blob/master/glove_dist.py
能够看到,我这个脚本函数使用到了两个第三方类库,各自是numpy和sklearn。希望没有装的朋友安装下,详细安装方法在此就不再赘述,有问题的能够和我交流。
这里说个插曲,我打开vectors.txt的时候发现它就是每行用空格切割,为首的是单词,后面接着就是这个单词所相应的向量,为了对照,我又打开了word2vec训练出来的vectors.txt(注意-binary 0)发现二者唯一的差别是,word2vec会在一開始写下单词个数与向量的维度。因此一个邪恶的念头在我脑海中飘过(自己在开头补上单词个数和向量维度),然后就能够被当成是word2vec的bin来被调用。这样可行吗?我一上来遇到个挫折,就是word2vec的原版.distance仅仅支持2进制的model的读入,但我不放弃,总算在python版本号的实现(gensim)中发现了load方法,为例如以下代码:
from gensim.models import Word2Vec model = Word2Vec.load_word2vec_format(‘vectors.txt’, binary=False)
喜欢调用gensim的其它函数的人能够自行玩耍。
说完插曲,能够看看我慘不忍睹的代码。假设不说我的list comprehensive 运行了两次split。也不说我的top k排序是基于所有排序的前K个(按理说K小的时候。用堆排序或者冒泡会更快),更不说我一上来没有进行向量归一化来降低计算时间,在这种情况下,我认为我的代码还是基本完毕任务了。
基本的两个函数分别用来进行余弦计算和找出与当前单词最相近的K个单词。以下又利用sklearn的kmeans对词向量聚类,本人已经用中文文本训练完毕。但因为时间限制,本文还是继续介绍怎样在维基的数据进行聚类。我会在以后的博客中介绍怎样对中文进行glove学习和聚类(假设还有下文)。
我特地在代码结尾出打印出china和father所相应的类别数(本例中为80和76),进入相相应的类别查看所属类别词。
我们能够看出,在china所相应的类别中,包括了非常多国家名,比方,germany,ireland, scotland等。在father所相应的第76类中,也包括了很多相关词汇,包括:child,son,wife,king。
当然我仅仅是列举几个好的,里面也包括非常多杂质,并且非常多类别以笔者的词汇是不清楚其详细的聚类含义。只是我们能够用这个100M的文本大体看到glove的初态,也算对得起入门二字。
最后把我训练好的vectors.txt和result目录放到github上,供大家查对结果:
https://github.com/eclipse-du/glove_py_model_load
下一步笔者会打算比較word2vec和glove的结果。以及分析glove运用在中文上面的效果,假设你们愿意看的话,去github上点个star(赞)。那样会加快我码文章的积极性。(弄到一点多不easy啊~~~)
假设对安装和我的脚本有不论什么疑问。欢迎及时和我联系。