重磅︱文本挖掘深度学习之word2vec的R语言实现

时间:2023-03-08 22:29:49

每每以为攀得众山小,可、每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~重磅︱文本挖掘深度学习之word2vec的R语言实现

———————————————————————————

笔者寄语:2013年末,Google发布的 word2vec工具引起了一帮人的热捧,大家几乎都认为它是深度学习在自然语言领域的一项了不起的应用,各种欢呼“深度学习在自然语言领域开始发力 了”。

基于word2vec现在还出现了doc2vec,word2vec相比传统,考虑单词上下文的语义;但是doc2vec不仅考虑了单词上下文的语义,还考虑了单词在段落中的顺序。

如果想要了解word2vec的实现原理,应该读一读官网后面的三篇参考文献。显然,最主要的应该是这篇: Distributed Representations of Words and Phrases and their Compositionality

这篇文章的基础是 Natural Language Processing (almost) from Scratch 其中第四部分提到了把deep learning用在NLP上。

,w2,⋯wT)=∏i=1Tp(wi|Contexti)

其中的Context表示的是该词的上下文,也就是这个词的前面和后面各若干个词,这个“若干”(后面简称c)一般是随机的,也就是一般会从1到5之间的一个随机数。

举个例子就是:“大家 喜欢 吃 好吃 的 苹果”这句话总共6个词,假设对“吃”这个词来说c随机抽到2,则“吃”这个词的context是“大家”、“喜欢”、“好吃”和“的”,总共四个词,这四个词的顺序可以乱,这是word2vec的一个特点。假设就是计算“吃”这个词的在“大家”、“喜欢”、“好吃”和“的”这四个词作为上下文的条件 概率,则

重磅︱文本挖掘深度学习之word2vec的R语言实现

其中 σ(x)=1/(1+ex) ,是sigmoid公式。

eE(wv,C)

1+eE(HG,C)

还是存在E能量难算,又把语料库切割下去。这个过程就像是建立分支树的过程。

Kp(dk|qk,C)=∏k=1K((σ(qkC))1−dk⋅(1−σ(qkC))dk)

这个公式是把p(A│C)=p(A|G,C)p(G|C) 中的语料库切割无数次之后得到的最终函数形式。那么求解函数,就得到了以下的似然函数,最后通过数学等式得到了如图所示的公式。

重磅︱文本挖掘深度学习之word2vec的R语言实现

dk表示树枝的左右向,dk=1向左分,dk=0向右分。

word2vec就是这么考虑的,把在霍夫曼树向左的情况,也就是dk=0的情况认为是正类,概率就可以算出来是σ(qijkContextij),而负向的(dk=1)就是1-σ(qijkContextij)。

每个叶子节点都产生一个样本,这个样本的label(也就是属于正类或者负类标 志)可以用霍夫曼编码来产生,前面说过了,向左的霍夫曼编码dk=0,所以很自然地可以用1-dk表示每个样本label。霍夫曼编码也变成了一个词向量之前很重要的东西。

2、Skip-gram模型(Skip-Gram(Continuous Skip-GramModel))

重磅︱文本挖掘深度学习之word2vec的R语言实现

词Wi与huffman树直接连接,没有隐藏层的。使用方法依然与cbow加层次的相似。在判断“大家 喜欢 吃 好吃 的 苹果”这句话是否自然语言的时候,是这么来的,同样比如计算到了“吃”这个词,同样随机抽到的c=2,对吃这个词需要计算的东西比较多,总共要计算的概率 是p(大家|吃),p(喜欢|吃),p(好吃|吃)和p(的|吃)总共四个。

P(吃︱Context)=p(大家|吃)×p(喜欢|吃)×p(好吃|吃)×p(的|吃)  其中p(大家│吃)=(1-σ(A?D))?σ(B?D)?σ(C?D)...(还有三个)

把一整句话的所有词的概率都计算出来后进行连乘,得到的就是这句话是自然语言的概率。这个概率如果大于某个阈值,就认为是正常的话;否则就认为不是自然语言,要排除掉【3】。

有一个比较简易的解读见【4】Skip-gram表示“跳过某些符号”。例如句子“中国足球踢得真是太烂了”有4个3元词组,分别是“中国足球踢得”、“足球踢得真是”、“踢得真是太烂”、“真是太烂了”,句子的本意都是“中国足球太烂”,可是上面4个3元组并不能反映出这个信息。

此时,使用Skip-gram模型允许某些词被跳过,因此可组成“中国足球太烂”这个3元词组。如果允许跳过2个词,即2-Skip-gram,那么上句话组成的3元词组为:

重磅︱文本挖掘深度学习之word2vec的R语言实现

由上表可知:一方面Skip-gram反映了句子的真实意思,在新组成的这18个3元词组中,有8个词组能够正确反映例句中的真实意思;另一方面,扩大了语料,3元词组由原来的4个扩展到了18个。
语料的扩展能够提高训练的准确度,获得的词向量更能反映真实的文本含义。

完成了两大目标:考虑距离更远的词语与当前词的关系;生成充分的语料库,并且有正确的词意词元。

———————————————————————————————————————————————

三、一些应用案例word2vec

1、广告推荐:布置在ANSJ上进行新闻关键词提取,抽调googlecode.com包,得到了计算每个词与最接近词之间的距离(distance)、还可以执行聚类【利用word2vec对关键词进行聚类】。

2、网络语料库包的训练实践:从网络的一些有名的语料包进行训练、在cygwin(因为word2vec需要linux环境,所有首先在windows下安装linux环境模拟器),抽调googlecode.com,并详细解释了函数系数。【Windows下使用Word2vec继续词向量训练

3、兴趣挖掘的必要性。利用word2vec给广告主推荐用户,只是简单分析没有实操,但是提到了论文《互联网广告综述之点击率系统》中的一些方法。【深度学习 word2vec 笔记】

———————————————————————————————————————————————

四、R语言中tmcn.word2vec

R语言中word2vec包,目前看到有一个叫tmcn.word2vec。该包真是一个草率、任性的包, 作者Jian Li,写于2014年9月21日。而且貌似后期也没有维护,不过作者貌似同时也在网上发布了word2vec自编译的函数。笔者猜测作者同时发布了两个版本用R实现word2vec的方式。

两种实现途径分别为:tmcn.word2vec包、自编译函数。

1、word2vec包的介绍

作者上传的word2vec包即为简单,只有两个函数,第一个函数是word2vec,第二个函数计算单词之间cos距离。两个函数基本没什么附加的参数可以调节。

包的下载地址可见链接:https://r-forge.r-project.org/R/?group_id=1571

或者通过install的方式,但是笔者未能通过下面的方式直接下载到。

install.packages("tmcn.word2vec", repos="http://R-Forge.R-project.org")

包中有三个demo案例,笔者在这贴出来:

(1)第一个demo

第一个是英文的word2vec方法的列举。

require(tmcn.word2vec)

# English characters
TrainingFile1 <- system.file("examples", "rfaq.txt", package = "tmcn.word2vec")
ModelFile1 <- file.path(tempdir(), "output", "model1.bin")

res1 <- word2vec(TrainingFile1, ModelFile1)
dist1 <- distance(res1$model_file, "object")
nrow(dist1)

先要设置word2sev之前的输入语料库文件(train_file)以及输出存放地(output_file)。其中model1.bin文件是一种二进制存放数据的方式,笔者打算用readBin来读取,但是没能实现。

distance代表在word2vec所得到的词向量中,“object”词与其他单词之间的距离(一般采用CosDist距离)。该函数给出了与object最近的20个词语。

(2)第二个demo

中文内容的,是金庸的小说为输入预料。

> TrainingFile2 <- system.file("examples", "xsfh_GBK.txt", package = "tmcn.word2vec")
> ModelFile2 <- file.path(tempdir(), "output", "model2.bin")
>
> res2 <- word2vec(TrainingFile2, ModelFile2)
Starting training using file ./R-3.2.2/library/tmcn.word2vec/examples/xsfh_GBK.txt
Vocab size: 1145
Words in train file: 27824
Alpha: 0.000000  Progress: 790.77%  Words/thread/sec: 22.69k  The model was generated in 'C:/Users/long/AppData/Local/Temp/Rtmpm460Qd/output'!
> dist2 <- distance(res2$model_file, intToUtf8(c(33495, 20154, 20964)))

Word: ���˷�  Position in vocabulary: 316
> dist2
   Word   CosDist
1  可是 0.3918099
2    呼 0.2853436
3    踏 0.2702354
4    多 0.2539852
5  眼光 0.2498445
6    较 0.2495218
7    盒 0.2491589
8  群雄 0.2380990
9  后面 0.2367072
10   几 0.2354743
11 一只 0.2346973
12 一齐 0.2282183
13   夺 0.2276031
14   他 0.2262077
15 </s> 0.2241129
16 一招 0.2232552
17 双刀 0.2226523
18   救 0.2194796
19   学 0.2124971
20   即 0.2113202

代码解读:输入的语料库是分好词的,intToUtf8(c(33495, 20154, 20964))是一个词——“苗人凤”。经过运算得出了与其最近的词,看前20个词貌似没有啥特别有用的信息。

(3)第三个demo代码

# Chinese characters in UTF-8 encoding, for *nix
TrainingFile3 <- system.file("examples", "xsfh_UTF8.txt", package = "tmcn.word2vec")
ModelFile3 <- file.path(tempdir(), "output", "model3.bin")

res3 <- word2vec(TrainingFile3, ModelFile3)
dist3 <- distance(res3$model_file, intToUtf8(c(33495, 20154, 20964)))
dist3

2、word2vec自编译函数

自编译函数需要自己布置一些环境,但是也只有两个函数,word2vec和distance函数。但是能够设置参数。自编译代码改写自google。应该这个自编译函数需要有这么几个步骤:

(1)仔细阅读.c.call extensions.pdf文件。其中详细写出了如何在电脑中搭建一个适用于R语言的二进制数据库;

(2)windows系统下,需要下载Rtools.exe文件,并改变环境变量的路径,同时重启计算机;

(3)看train_word2vec.R,其中有R中如何调用word2vec的API。

具体的可以从 http://download.csdn.net/download/sinat_26917383/9513075 下载得到完整的自编译函数、说明以及上述提到的PDF文档。

笔者在这简单叙述一下word2vec函数中的一些参数:

word2vec <- function (train_file, output_file,
                      binary=1,                                # output format, 1-binary, 0-txt
                      cbow=0,                                  # skip-gram (0) or continuous bag of words (1)
                      num_threads = 1,                         # num of workers
                      num_features = 300,                      # word vector dimensionality
                      window = 10,                             # context / window size
                      min_count = 40,                          # minimum word count
                      sample = 1e-3,                           # downsampling of frequent words
                      classes = 0
                      ) 

  # The parameters:
  #                binary       - output format of the model;
  #
  #                cbow         - which algorithm to use for training or skip-gram bag of words (cbow).
  #                               Skip-gram is slower but produces a better result on the rare words;
  #
  #                num_threads  - Processor number of threads involved in the construction of the model;
  #
  #                num_features - the dimension of words (or a vector for each word), it is recommended from tens to hundreds;
  #
  #                window       - as many words from the context of the training algorithm should be taken into account;
  #
  #                min_count    - limits the size of a boost word dictionary.
  #                               Words that are not found in the text more than the specified number are ignored.
  #                               Recommended value - from ten to one hundred;
  #
  #                sample       - the lower limit of the frequency of occurrence of words in the text,
  #                               it is recommended from .00001 to .01. 

以下关于参数的解释是来源于linux环境模拟器,cygwin中操作,用Java来调用的,发现R中这个包也跟这个函数参数,大同小异,而且解释很清楚,所以非常感谢作者的细心翻译[1]。

参数解释:
-train_file 训练数据
-output_file 结果输入文件,即每个词的向量
-cbow 是否使用cbow模型,0表示使用skip-gram模型,1表示使用cbow模型,默认情况下是skip-gram模型,cbow模型快一些,skip-gram模型效果好一些
-num_features 表示输出的词向量维数
-window 为训练的窗口大小,8表示每个词考虑前8个词与后8个词(实际代码中还有一个随机选窗口的过程,窗口大小<=5)
-sample 表示 采样的阈值,如果一个词在训练样本中出现的频率越大,那么就越会被采样
-binary 表示输出的结果文件是否采用二进制存储,0表示不使用(即普通的文本存储,可以打开查看),1表示使用,即vectors.bin的存储类型
-------------------------------------
除了上面所讲的参数,还有:
-alpha 表示 学习速率
-min-count 表示设置最低频率,默认为5,如果一个词语在文档中出现的次数小于该阈值,那么该词就会被舍弃
-classes 表示词聚类簇的个数,从相关源码中可以得出该聚类是采用k-means

模型训练完成之后,得到了.bin这个词向量文件,文件的存储类型由binary参数觉得,如果为0,便可以直接用编辑器打开,进行查看.其中word2vec中提供了distance求词的cosine相似度,并排序。也可以在训练时,设置-classes参数来指定聚类的簇个数,使用kmeans进行聚类。

disttance函数。

由于word2vec计算的是余弦值,距离范围为0-1之间,值越大代表这两个词关联度越高,所以越排在上面的词与输入的词越紧密[2]。

distance(file_name, word,size)

输出是一个list,然后可以得到cos距离。
一个在线测试的网站,貌似是一位清华教授做的:http://cikuapi.com/index.php[2]

3、关于两者体会

(1)word2vec的自编译函数在使用时也需要加载tmcn.word2vec包,笔者在使用过程中直接调用word2vec函数的话,会出现一下的error情况:

Error in .C("CWrapper_word2vec", train_file = as.character(train_file),  :
  C symbol name "CWrapper_word2vec" not in load table

(2)tmcn.word2vec与word2vec自编译是可以互补的。在require(tmcn.word2vec)之后,可以直接调用word2vec函数,而且自编译函数可以调节参数,而且有一个非常bug的功能,可以自行聚类,这个非常厉害,并且可以通过cbow=0的参数选择使用CBOW模型还是skip-gram模型,并且通过binary=0参数可以调整输出的是txt文件,而且tmcn.word2vec包中输出只有.bin文件,难以读取。

(3)tmcn.word2vec与word2vec自编译中两个word2vec生成不一样的语料库,同时执行distance函数之后也计算不一样的词距离。(接下来的结论,是由笔者自己推测)语料库不同的原因:因为CBOW模型与Skip-gram模型在抽取近邻词的时候也会采用随机抽样的方法,所以会产生不一样的结果;distance函数不同的原因,因为语料库的不同,笔者在设定了(set.seed)随机数之后,得到了相同的distance结果。

(4)笔者推断最佳的使用tmcn.word2vec步骤是:加载包(require(tmcn.word2vec))、执行自编译函数(word2vec/distance)、设定随机数(set.seed)(很关键,会影响输出结果)、用自编译函数来执行分析任务(选择模型、是否聚类、是否输出txt文件、词维度、词数量等)。

———————————————————————————————————————————————

四、text2vec包

该包写于2016年3月21日,全名是Fast Text Mining Framework for Vectorization and Word Embeddings,矢量化词向量文本挖掘模型。

关于这个包,有待研究。

参考博客:

1、Windows下使用Word2vec继续词向量训练

2、利用word2vec对关键词进行聚类

3、深度学习 word2vec 笔记4、word2vec词向量训练及中文文本相似度计算5、word2vec——高效word特征求取
6、《Word2vec的工作原理及应用探究 · 周练 · 西安电子科技大学2014年》
7、《Word2vec对中文词进行聚类的研究 · 郑文超,徐鹏 · 北京邮电大学2013年》

8、《Word2vec的核心架构及其应用 · 熊富林,邓怡豪,唐晓晟 · 北邮2015年》

每每以为攀得众山小,可、每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~重磅︱文本挖掘深度学习之word2vec的R语言实现

———————————————————————————