语⾔模型系列之N-Gram、NPLM及Word2vec
根据上⽂公式1 ,词w出现的在序列位置T的概率取决于序列前⾯1~T-1所有词,⽽这样的模型参数空间巨⼤,训练计算量惊⼈且数据稀疏。⽽BOW(unigram)中,每维特征信息量过少。 依据著名马尔科夫假设(Markov Assumption),在N-gram中词T的概率仅仅受前N-1个词影响。N元模型公式
举个经典的⼆元语⾔模型(Bi-gram)例⼦:
图1: ⼆元语⾔模型实例(左为语料库中词频和词序列,右为“I want to eat Chinese food”概率计算过程)
图2:⼆元LM中句⼦概率计算
N-gram对中⽂词性标注(part of speech, POS)、中⽂分词(Word Segmentation)有很好的效果。中⽂分词和POS是中⽂⽂本分析中⾮常重要的⼀环,因此在此作为N-gram的应⽤简要介绍。此外,基于N-gram还出现了更多有价值的语⾔模型,如NNLM、CBOW等。
1.中⽂词性标注 - NGram应⽤
词性标注(POS tagging)是个典型的多分类问题,将每个词标注为名词、动词、形容词、副词、代词等(可能更细分)。举个例⼦,
在“我/爱/北京”这句中,“爱”有很多词性,⽐如名词、动词。最简单的标注其语义的⽅案就是,看语料库中“爱”出现的次数。即
然⽽这种极简POS Tagging的⽅案依赖⼈⼯,且尚未考虑上下⽂。考虑到词性与前⼀两个词关系较⼤,因此我们引⼊N-Gram模型,最简单的⽐如前⽂提到的bi-gram模型,即在考虑“爱”的POS时考虑“我”的词性。则当前这个“爱”的词性概率分布为
计算这个概率需要对语料库进⾏统计。但前提是你得先判断好“我”的词性,因为采⽤2-gram模型,由于“我”已经是第⼀个词,在⼆元模型中只需要⽤极简的⽅案判断即可。利⽤NLTK的POS Tagger,可以轻松进⾏中⽂词性标注。在下⼀节分词中将po出代码。
2.中⽂分词 - NGram应⽤
中⽂分词在中⽂语义分析中有着绝对重要核⼼的地位。根据的介绍, 中⽂分词,重要到某搜索引擎⼚有专门的team在集中精⼒优化这⼀项⼯作,重要到能影响双语翻译10%的准确度,能影响某些query下搜索引擎⼏分之⼀的⼴告收⼊。
对于X = “我爱北京”这样⼀句话,有N中分词⽅案,对于
这种分词⽅案,如 =(“我”“爱”“北京”)、
=(“我”“爱北”“京”)、(“我爱”“北京”)…, 套⽤贝叶斯公式有:
⽽⽆论在哪种 下,最终都能⽣成句⼦X。因此 为1。 。则只需要最⼤化 即可。例如,在bi-gram语⾔模型中, , 。根据语料库,P(京|爱北)的概率接近0, 较⼤,则采⽤这种分词策略。利⽤python的jieba库可以进⾏中⽂分词和词性标注,⽰例如下。
import jieba
import jieba.posseg刘亦菲裸妆照片大全
#中⽂分词
s = '我爱北京'
seg = jieba.cut(s)
for i in seg:
print(i)
#中⽂词性标注
seg_pos = jieba.posseg.cut(s)
for i in seg_pos:
print(i.word, i.flag)
Output:
挥着翅膀的女孩英文版歌词我
北京
(u'\u6211', u'r')
(u'\u7231', u'v')
(u'\u5317\u4eac', u'ns')
1
2
3
谢天华个人资料4
5
许嵩 叹服
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
3.从N-gram到NNLM
对N-gram的训练也产⽣了其他⼀些语⾔模型。著名的神经⽹络语⾔模型(NNLM)就是其中的典型代
表。说⾼⼤上的NNLM是由N-gram 演化⽽来的,这种理解的逻辑依据是——考虑前后⽂的量。下⼀篇中会讲到RNNLM及其延伸,其考虑前后⽂的量理论上将扩展为全⽂(
)。在此篇我们只考虑固定个(N)上下⽂的情况。
Bengio》NNLM经典之作,他提出利⽤三层神经⽹络构建语⾔模型。结构如图三。
图三:神经⽹络语⾔模型 by Bengio
图三中,C(w)为词w对应的词向量,为V*m维矩阵(V为总词数,m为词向量维度)。
神经⽹络(NN)的输⼊层为当前词
的前n-1个词 各⾃的词向量(即word embedding)相拼接,合计共 维。
NN的隐藏层与普通NN⽆异,以tanh双曲正切函数作为激活函数。
NN的输出层共V个节点,对应每个词作为 的log概率。可通过softmax函数对输出值y进⾏归⼀化为概率。
输⼊层直连输出层注意,存在权重矩阵
, 直接关联了输⼊层与输出层。
故神经⽹络输出表达式如下:
V中每个词的词向量(word embedding)都存在于权重矩阵C中。故NLPM除了学习Weight和bias,还同时对输⼊层的词向量进⾏训练。模型的参数为C, U, H, W, b, d.模型对 的损失函数即为:
整个模型的损失函数即为:
非诚勿扰 许秀琴通过梯度下降训练参数更新过程如下:
离人歌词详细更新过程、数学原理及简要实现可以参考这篇。NPLM的python实现可以参考yuriyfilonov的或者greninja的实现版本。
4.CBOW & Skip-gram
在NNLM的基础上,CBOW和Skip-gram可以理解为其两个特殊的变种,区别在于去掉了NPLM的隐藏层,⽽着重突出了输⼊层one-hot到word embedding这⼀步(毕竟,⼤家听说CBOW&Skip-gram都是从word2vec开始的嘛哈哈,别说你不是,⼤神受⼩妹⼀跪!)。与以上模型相似的是,它们同样考虑前后⽂,依然逃脱不了N-Gram语⾔模型的基因。只不过,CBOW通过上下⽂预测中⼼词概率,⽽Skip-gram模型则通过中⼼词预测上下⽂的概率。如图所⽰,模型与⼤体⽆异,这⾥着重介绍CBOW模型。
本⽂介绍的是⼀个经典且简单的CBOW模型,是来⾃Google的Tomas Mikolov 2013年中的版本。图⽚推导参考[4]。
下图展⽰了⼀个多词上下⽂(context=multi_words)的CBOW模型。前⾯提过CBOW模型与NPLM的主要区别再去去掉了隐藏层,⽽图中提到的Hidden Layer实际并没有涉及任何⾮线性激活操作(如上⽂NPLM中的tanh),⽽仅仅是对输⼊层通过权重矩阵得到的词向量求平均。因此图中我将其标记成映射层(Projection Layer)。
符号定义: 语料库为D,词汇总数V;考虑上下⽂词语数C个,分别表⽰为
;映射层/词向量维度为N; 为词汇w的One-hot Representation,V维; 为词汇w的词向量,N维。
输⼊层: 输⼊层的节点为C个上下⽂词语的one-hot表⽰,共C*V输⼊节点。
映射层: 将输⼊层节点乘上权重矩阵
得到的词向量(word embedding)求平均得到h。公式如下。
输出层: 映射层经过 权重矩阵后,得到V维z, 再对z进⾏softmax操作得到中⼼词为某个词j的概率分布。公式如下。
故该模型对于中⼼词w_t的损失为:
加和得到模型总损失函数为
故从映射层到输出层的权重更新如下(详细推导参考[4]):
输⼊层到映射层的权重更新如下:
以上是CBOW模型的结构及简单推导,提供了CBOW模型的实现,仅供⼤家参考学习。
虽然CBOW模型对NPLM模型进⾏了简化,但由于仍然包含softmax操作⽽耗时严重。[4]⽂中给出了层次softmax+负采样的⽅式对训练进⾏加速,[5]⽂对其进⾏了深化和整理,在此不再展开。
5.副产品Word2vec
不管是NPLM还是CBOW、Skip-gram,除了训练得到语⾔模型,还得到了副产品词向量,可以将语料库中的词通过权重矩阵得到更make sense且⾮稀疏的向量表达,同时还能将语义甚⾄语法通过空间距离的⽅式进⾏呈现,⽐如NLPer们熟知的“king-
man+woman=queen”和“queen+kings-king=queens”的例⼦。这就是的词向量不仅在更多复杂语⾔模型中发挥作⽤,还有更多奇妙的应⽤,⽐如相似度度量,进⽽进⾏⽂本分类聚类,完成情感分析、关系挖掘等有趣的任务。
Python中的提供了word2vec的API,可以对词向量进⾏创建、训练、保存、重训练等操作,并利⽤其进⾏相似性度量等。
model = Word2Vec(docs, size=100, window=5, min_count=5, workers=2) #利⽤sentences构建词向量
model.save(file_path)  #将训练好的词向量进⾏保存
model = Word2Vec.load(file_path) #从⽂件载⼊模型,重训练或使⽤
model.wv['computer']  #查computer的词向量
output:
array([-0.00449447, -0.00310097,  0.02421786, ...], dtype=float32)
st_similar(positive=['woman', 'king'], negative=['man'])  #利⽤词向量计算词语间的空间关系
Output:
[('queen', 0.50882536), ...]
model.wv.similarity('woman', 'man') #计算两个词的相似度
Output:
0.73723527
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
附:Word2Vec参数说明