• 利用中文数据跑Google开源项目word2vec


    word2vec注释

    1、多线程并行处理:

    1、分配内存空间,创建多线程,执行多线程。malloc,pthread_create,pthread_join 
    2、每个多线程处理的训练文档根据线程id,分配不同的文档内容,由fseek定位


    2、vocab相关:

    1、每个vocab对象都含以下内容:词(char[]),词频(long long),词在哈夫曼树中的父节点们(可以理解为编码的次序)(int*),哈夫曼编码(char*),哈夫曼码长度(char) 
    2、获取vocab词典有两条路径: 
    1、是从词典文件直接读取。这个要求第一行是,也就是句子的分隔符(如果在训练语料里没有这个分隔符,则基本默认1000个词(最长句子长度)为一句话) 
    第二,每行应该是一个词后面接词频信息 
    2、从训练语料中统计。如果没指定词典文件,则在训练之前,程序会先遍历一边文档,统计出词典信息。 
    3、vocab的添加是增量式的,比如最初是1000的大小,当空间不够的时候会再添加2000,再不够,再添加3000,每次添加的数额比上次多1000 
    4、程序中设定了vocab_hash_size是300W,如果要求装填因子在0.7左右,则vocab中词的个数不应该超过210W,所以当个数超过210W的时候就会删除词频比较低的词 
    最开始设置的删除词频为1(min_reduce)及以下的词,再次超过210W的时候,min_reduce会加1,删除词频<=2的词,一直如此 
    5、在添加vocab的时候,同时维护了一张vocab_hash的哈希表 
    1、vocab_hash的key是词通过hash函数得出的int型值,value是这个词在vocab中的下标(从0开始),vocab_hash就是一个int型数组 
    2、获取word的hash key值得hash函数如下:for (a = 0; a < strlen(word); a++) hash = hash * 257 + word[a]; 
    3、解决冲突的方法就是开放地址法,while (vocab_hash[hash] != -1) hash = (hash + 1) % vocab_hash_size;向下顺移 
    4、vocab_hash的构建是为了方便查找 
    6、在统计完成之后需要对vocab进行排序,按照词频的大小逆序排序, 
    1、第一个词,也就是不进行排序 
    2、排完序之后,需要将词频小于min_count的词去掉(直接free) 
    2、排完序之后,需要对vocab_hash重新就行计算


    3、net initialization相关:

        1、初始化三个矩阵,syn0(vocab_size*layer1_size),syn1(vocab_size*layer1_size),syn1neg(vocab_size*layer1_size)
        2、vocab_size是词表的大小,layer1_size即词向量的维数
        3、syn0用一个-0.005~0.005之间的数随机初始化里面的元素,syn1,syn1neg直接用0初始化
        4、syn0就是最后得到的词的词向量,与vocab相呼应;即vocab[i].word这个词的词向量时syn0中的第i行(i从0开始)
        5、syn1是用hierachical softmax算法时候的辅助矩阵,syn1neg是用negative sampling算法时候的辅助矩阵
        6、syn1的每一行可以认为是哈夫曼树中的一个非叶子节点,这一行应该就代表了以他为祖先的叶子节点(词)的综合含义;
                对于一个哈夫曼树,如果有N个叶子节点,则有N-1个非叶子节点,所以syn1和syn1neg里面的最后一行应该是无意义的
                行数越大,代表的词也就越多,如第V-2行(哈夫曼树的根节点)理论上代表了所有词的意思
        7、syn1neg的每一行与vocab相呼应,也就是vocab[i].word这个词在做负样本时有一个向量的表示,在syn1neg的第i行(从0开始)
    

    4、binary tree create相关:

        1、用词频进行编码,词频越大的词的编码长度越小
        2、用了三个2*vocab_size的long long 型数组,代码比较巧妙,可以学学
        3、初始化vocab结构体其他的成员:codelen,code(从上到下),point(从上到下跟该词相关的节点(不包括根节点)/该词相应code的编码时机次序)
    

    5、训练相关:

    1、每训练10000个词打印一次progress信息,并更新学习速率alpha(starting_alpha是0.025) 
    2、同时每次是取出一句话后再进行训练,处理完一句话后,再读取下一句,循环迭代

                1、读取句子时,以</s>分隔符为标识,如果没有</s>则以上届1000个词为一句话。ps:在训练的时候是将换行符换成了</s>的
                2、如果选择的了sub_sampling,则在遍历训练文档,构建句子的过程中,会随机的忽视掉一些频率比较高的词,具体方法可以看代码,不太懂
    

    3、在程序执行过程中,每次的词窗大小是在随机变化的,如果设置参数-window 5,则窗口的大小就是3~11之间,也就是前k个词+后k个词+中间词,k在1~5之间

    4、有两个向量值得关注:neu1,neu1e,都是layer1_size的大小,在cbow和skip gram model中具体略有不同

    5、cbow模型:

    1、cbow模型就是continuous bag of words,根据前k个词和后k个词预测中间词 
    2、找到前k个词和后k个词在vocab中的位置,并从syn0中找出他们的词向量,各维数相加,得到一个layer1_size的向量,即neu1 
    3、用hierachical softmax算法时,需要根据该词的每一位code编码进行计算,假定第j位code:

                    1、先找到该位code在哈夫曼树中的位置(存储在vocab[i].point[j]中),然后以此位置在syn1中找到对应的向量
                    2、用neu1与syn1中的这行向量相乘,得到f值,这个f就是输出值,然后对f进行归一化,映射到0~1之间
                    3、这点跟逻辑回归有点类似。在程序中,把softmax的label设置的是1-code[j],这个label就是logistic regression里面的真实值,f就是猜测
                    4、通过3,和逻辑回归的理论类推,我们就能得到一个loss function 或者负log 似然函数
                    5、loss function关于两个向量(neu1和syn1中的那行)的梯度共同部分为(1 - vocab[word].code[d] - f),对了,还有一个学习速率
                    6、 更新neu1e和syn1[vocab[i].point[j]],比如更新neu1,就用g = (1 - vocab[word].code[d] - f) * alpha;neu1e = g.*syn1[vocab[i].point[j]](标量与向量的乘积)
                                更新syn1[vocab[i].point[j]],syn1[vocab[i].point[j]] = g.*neu1;
    

    4、用negative sampling算法时,并不需要考虑code编码的问题:

                    1、在参数设置的时候,假设我们选定了negative samples 为k个
                    2、我们随机的在词表当中抽取k个negative samples 词,当然有可能会抽到与当前这个词相同(虽然概率很小),我们就pass过去,也就是说真实的negative samples可能没有k个
                    3、假设我们现在考虑的是第j个negative sample,则从syn1neg里面找到j的向量表示,同neu1(上下文向量表示)相乘,得到输出值f,同样归一化
                    4、这里的g与hs中的g有点不同,这里g = (label-f)*alpha;如果是负样本的话label是0,如果是当前词label是1
                    5、更新neu1e和syn1neg[vocab[i].point[j]],同3.6
    

    5、在上述第3或第4步处理完毕后,我们有一个neu1e的向量,我们再用这个neu1e去更新前k个词和后k个词的词向量,就是syn0里面的2k维向量(直接相加),从而完成了一个窗口的迭代更新 
    6、skip-gram 模型:

                1、skip-gram model与cbow正好相反,是根据当前词来预测前k个和后k个词
                2、假设现在当前词为cur_word,而我们要推测出窗口中的某个词last_word,last_word在窗口中,有2*k个这样的last_word都需要推测
                3、用hierachical softmax算法时,同样需要对cur_word的每一位code编码进行计算,假定第j位code:
                    1、找到last_word在vocab中的位置,以此位置在syn0中找到对应的向量
                    2、先找到该位code在哈夫曼树中的位置(存储在vocab[i].point[j]中),然后以此位置在syn1中找到对应的向量
                    3、用last_word的向量与syn1中的这行向量相乘,得到f值,这个f就是输出值,然后对f进行归一化,映射到0~1之间
                    4、同样计算出梯度,并通过梯度来更新neu1e和syn1,具体的和cbow-hs几乎一样
                4、用negative sampling算法时,所有流程基本与cbow的negative sampling一样,唯一的区别就是不是用neu1向量与syn1neg相乘,而是用last_word的词向量
    

    6、tips:

        1、程序中在对输出值f进行0~1之间映射的时候,是提前算好了一个数组expTable,这个数组的值在0.01~1(1/(1+e-6)~1/(1+e6))之间,所以f值小于-6或者大于6就continue了。
        2、在进行negative sampling的时候,随机选择的word是和word的概率的power次方成正比的
        3、随机数的生成:每次乘以一个很大的数,然后加11,然后取模,然后归一化

    word2vec训练参数说明

    训练命令:

    ./word2vec -train text8 -output vectors.bin -cbow 1 -size 200 -window 8 -negative 25 -hs 0 -sample 1e-4 -threads 20 -binary 0 -iter 15
    ./distance vectors.bin

    中的text8更改成自己的训练数据名称all_words,如果你的数据有后缀,记得带后缀。 
    这里写图片描述
    参数解释: 
    -train 训练数据 
    -output 结果输入文件,即每个词的向量 
    -cbow 是否使用cbow模型,0表示使用skip-gram模型,1表示使用cbow模型,默认情况下是skip-gram模型,cbow模型快一些,skip-gram模型效果好一些 
    -size 表示输出的词向量维数 
    -window 为训练的窗口大小,8表示每个词考虑前8个词与后8个词(实际代码中还有一个随机选窗口的过程,窗口大小<=5) 
    -negative 表示是否使用NEG方,0表示不使用,其它的值目前还不是很清楚 
    -hs 是否使用HS方法,0表示不使用,1表示使用 
    -sample 表示 采样的阈值,如果一个词在训练样本中出现的频率越大,那么就越会被采样 
    -binary 表示输出的结果文件是否采用二进制存储,0表示不使用(即普通的文本存储,可以打开查看),1表示使用,即vectors.bin的存储类型

    除了上面所讲的参数,还有: 
    -alpha 表示 学习速率 
    -min-count 表示设置最低频率,默认为5,如果一个词语在文档中出现的次数小于该阈值,那么该词就会被舍弃 
    -classes 表示词聚类簇的个数,从相关源码中可以得出该聚类是采用k-means

    ===============================================================

    一直听说word2vec在处理词与词的相似度的问题上效果十分好,最近自己也上手跑了跑Google开源的代码(https://code.google.com/p/word2vec/)。

    1、语料

    首先准备数据:采用网上博客上推荐的全网新闻数据(SogouCA),大小为2.1G。

    从ftp上下载数据包SogouCA.tar.gz:
    1 wget ftp://ftp.labs.sogou.com/Data/SogouCA/SogouCA.tar.gz --ftp-user=hebin_hit@foxmail.com --ftp-password=4FqLSYdNcrDXvNDi -r

    解压数据包:

    1 gzip -d SogouCA.tar.gz
    2 tar -xvf SogouCA.tar

    再将生成的txt文件归并到SogouCA.txt中,取出其中包含content的行并转码,得到语料corpus.txt,大小为2.7G。

    1 cat *.txt > SogouCA.txt
    2 cat SogouCA.txt | iconv -f gbk -t utf-8 -c | grep "<content>" > corpus.txt

    2、分词

    用ANSJ对corpus.txt进行分词,得到分词结果resultbig.txt,大小为3.1G。

    分词工具ANSJ参见 http://blog.csdn.net/zhaoxinfan/article/details/10403917
    在分词工具seg_tool目录下先编译再执行得到分词结果resultbig.txt,内含426221个词,次数总计572308385个。
     分词结果:
     
    3、用word2vec工具训练词向量
    1 nohup ./word2vec -train resultbig.txt -output vectors.bin -cbow 0 -size 200 -window 5 -negative 0 -hs 1 -sample 1e-3 -threads 12 -binary 1 &

    vectors.bin是word2vec处理resultbig.txt后生成的词的向量文件,在实验室的服务器上训练了1个半小时。

    4、分析
    4.1 计算相似的词:
    1 ./distance vectors.bin

    ./distance可以看成计算词与词之间的距离,把词看成向量空间上的一个点,distance看成向量空间上点与点的距离。

    下面是一些例子:

    4.2 潜在的语言学规律

    在对demo-analogy.sh修改后得到下面几个例子:
    法国的首都是巴黎,英国的首都是伦敦, vector(“法国”) – vector(“巴黎) + vector(“英国”) –> vector(“伦敦”)”

    4.3 聚类

    将经过分词后的语料resultbig.txt中的词聚类并按照类别排序:

    1 nohup ./word2vec -train resultbig.txt -output classes.txt -cbow 0 -size 200 -window 5 -negative 0 -hs 1 -sample 1e-3 -threads 12 -classes 500  &
    2 sort classes.txt -k 2 -n > classes_sorted_sogouca.txt

    例如:

    4.4 短语分析

    先利用经过分词的语料resultbig.txt中得出包含词和短语的文件sogouca_phrase.txt,再训练该文件中词与短语的向量表示。

    1 ./word2phrase -train resultbig.txt -output sogouca_phrase.txt -threshold 500 -debug 2
    2 ./word2vec -train sogouca_phrase.txt -output vectors_sogouca_phrase.bin -cbow 0 -size 300 -window 10 -negative 0 -hs 1 -sample 1e-3 -threads 12 -binary 1

    下面是几个计算相似度的例子:

    5、参考链接

    1. word2vec:Tool for computing continuous distributed representations of words,https://code.google.com/p/word2vec/

    2. 用中文把玩Google开源的Deep-Learning项目word2vec,http://www.cnblogs.com/wowarsenal/p/3293586.html

    3. 利用word2vec对关键词进行聚类,http://blog.csdn.net/zhaoxinfan/article/details/11069485

    6、后续准备仔细阅读的文献:

    [1] Tomas Mikolov, Kai Chen, Greg Corrado, and Jeffrey Dean. Efficient Estimation of Word Representations in Vector Space. In Proceedings of Workshop at ICLR, 2013.
    [2] Tomas Mikolov, Ilya Sutskever, Kai Chen, Greg Corrado, and Jeffrey Dean. Distributed Representations of Words and Phrases and their Compositionality. In Proceedings of NIPS, 2013.
    [3] Tomas Mikolov, Wen-tau Yih, and Geoffrey Zweig. Linguistic Regularities in Continuous Space Word Representations. In Proceedings of NAACL HLT, 2013.

    [4] Collobert R, Weston J, Bottou L, et al. Natural language processing (almost) from scratch[J]. The Journal of Machine Learning Research, 2011, 12: 2493-2537.

     
    来源:http://www.cnblogs.com/hebin/p/3507609.html

    转载请注明:人人都是数据咖 » 利用中文数据跑Google开源项目word2vec

  • 相关阅读:
    网络编程--ASI--(ASIHTTPRequest)介绍
    iOS-多线程--介绍NSOperration
    单例模式-用GCD实现
    ios文件读取(二)
    归档、反归档
    ios文件读取
    CUICatalog: Invalid asset name supplied:
    iOS的触摸事件
    UIScrollView的属性
    exc_bad_access(code=1, address=0x789870)野指针错误
  • 原文地址:https://www.cnblogs.com/hd-zg/p/6841413.html
Copyright © 2020-2023  润新知