词向量随记1

学习NLP先从一些基本的CASE 入手吧,比如训练条件随机场,训练词向量。会用工具也是一种技能,请不要小瞧这种能力,他山之石可以攻玉。言归正传
今天从词向量开始。

资源

https://code.google.com/archive/p/word2vec/
https://code.google.com/p/word2vec/
https://github.com/svn2github/word2vec

训练准备

讲一下程序的编译,如果在Linux下我们可以直接make(要求有gcc)

训练参数说明

训练时需要有语料,假设我们有语料 test.txt ,那么可以按照以下的方式进行训练
./word2vec -train text.txt -output vectors.bin -cbow 0 -size 48 -window 5 -negative 0 -hs 1 -sample 1e-4 -threads 20 -binary 1 -iter 100
参数说明:
-train text8 表示的是输入文件是text,
-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,进行参数传递无效。

注意事项

:skip-gram(慢、对罕见字有利)vs CBOW(快)
· 训练算法:分层softmax(对罕见字有利)vs 负采样(对常见词和低纬向量有利)
· 欠采样频繁词:可以提高结果的准确性和速度(适用范围1e-3到1e-5)
· 文本(window)大小:skip-gram通常在10附近,CBOW通常在5附近

算法讲解

对于word2vec 我觉得下面这个帖子讲得比较清楚,在学习的过程中记录一下个人的心得体会。这里会把一些重要的细节做节选,摘抄甚至批注,方便日后习。详细请参见http://www.hankcs.com/nlp/word2vec.html

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 …]
其实这样做的一个最主要的问题是矩阵稀疏性。

这样的表示方式还存在着一个弊端,就是词与词的表示是独立的,不包含任何上下文的信息量。但是上下文的信息对词究竟有多少帮助呢?看看N-gram 模型就知道了。

语言模型形式化的描述就是给定一个 T 个词的字符串 s,看它是自然语言的概率
P(w1,w2,…,wt)。w1 到 wT 依次表示这句话中的各个词。有个很简单的推论是:
词向量随记1
如一句话“大家喜欢吃苹果”,总共四个词“大家”,“喜欢”,“吃”,“苹果”,怎
么分词现在不讨论,总之词已经分好,就这四个。那么这句话是一个自然语言的概率是:
P(大家,喜欢,吃,苹果)=p(大家)p(喜欢|大家)p(吃|大家,喜欢)p(苹果|大家,喜欢,吃)
p(大家)表示“大家”这个词在语料库里面出现的概率;
p(喜欢|大家)表示“喜欢”这个词出现在“大家”后面的概率;
p(吃|大家,喜欢)表示“吃”这个词出现在“大家喜欢”后面的概率;
p(苹果|大家,喜欢,吃)表示“苹果”这个词出现在“大家喜欢吃”后面的概率。
所以看来词与词之间还是存在一定的关系的啊!

2.词向量

简单来说就是,对词典D中的任意词w,指定一个固定长度的实值向量词向量随记1v(w) 就称为w的词向量,m 称为词向量的长度。其实说白了词向量干的事情就是把词向量化表示。
如果用神经网络表示词,就需要包括四个层:输入层(Input layer), 投影层(Projection layer), 隐藏层(Hidden layer)和输出层(Output layer).如下图所示:
词向量随记1
然后又简化了 投影层(Projection layer) ,变成了三层网络,如下图所示:
词向量随记1

所以根据上面的三层网络结构就衍生出来今天的Word2Vector的网络结构,如下图所示:
词向量随记1
其中w(t)代表当前词语位于句子的位置t,同理定义其他记号。在窗口内(上图为窗口大小为5),除了当前词语之外的其他词语共同构成上下文。
其实这种图已经是被用烂地一张图,但是再没有看到前面两张图的时候,总觉得有些突兀。为什么会这么设计呢?现在看了一切了然,据说word2vec的作者嫌从hidden layer到output layer的矩阵运算太多了才把四层网络改为了三层,如果不是这一改,上面关于CBOW 和Skip-gram的结构图可能还需要加一层啊。这里补一下 关于这种衍变的数学原理,节选自《word2vec中的数学原理》中:
词向量随记1
注:上段文字中提到的图4就是上文的“神经网络结构示意图”

CBOW

CBOW 是 Continuous Bag-of-Words Model 的缩写,是一种根据上下文的词语预测当前词语的出现概率的模型。CBOW是已知上下文,估算当前词语的语言模型。其学习目标是最大化对数似然函数:
词向量随记1

其中,w表示语料库C中任意一个词。从CBOW Model 示意图可以看出,对于CBOW,输入层是上下文的词语的词向量。
投影层对其求和,所谓求和,就是简单的向量加法。
输出层输出最可能的w。由于语料库中词汇量是固定的|C|个,所以上述过程其实可以看做一个多分类问题。给定特征,从|C|个分类中挑一个。
对于神经网络模型多分类,最朴素的做法是softmax回归:
词向量随记1
非叶子节点相当于一个神经元,二分类决策输出1或0,分别代表向下左转或向下右转;每个叶子节点代表语料库中的一个词语,于是每个词语都可以被01唯一地编码,并且其编码序列对应一个事件序列,于是我们可以计算条件概率

词向量随记1
词向量随记1
词向量随记1
怎么最大化对数似然函数呢?分别最大化每一项即可(这应该是一种近似,最大化某一项不一定使整体增大,具体收敛的证明还不清楚)。怎么最大化每一项呢?先求函数对每个变量的偏导数,对每一个样本,代入偏导数表达式得到函数在该维度的增长梯度,然后让对应参数加上这个梯度,函数在这个维度上就增长了。这种白话描述的算法在学术上叫随机梯度上升法
词向量随记1
词向量随记1