(⼀)⽂本嵌⼊式表⽰⽅法实战(词、句和段落向量:
Word2Vec,GloVe,Paragr。。。
《⽂本嵌⼊式表⽰⽅法实战》系列⽂章是基于2017年我于研⼀下半学期做的两场长时间的组会汇报ppt上形成的⽂章(学习和实验长达3个⽉,因为当时主要以上课为主,实验都是课余时间做的。。),由于当时我正处于⼊门阶段,理解和表述定有不当之处,还请各位同学⽼师批评指教。。。
《⽂本嵌⼊式表⽰⽅法实战》系列⽂章全部链接如下:
1 前⾔
⽂本特征提取和表⽰⽅法历来是⾃然语⾔处理的核⼼问题之⼀,因为⽂本是符号数据,只要两个词只要构成的字不同或者构成的字相同就难以刻画他们之间的关系(例如“麦克风”和“话筒”这样的同义词,从字⾯上看不出两者含义相同)。
⾃然语⾔处理与图像处理和语⾳处理不同的地⽅是⽂本是符号数据,图像和语⾳的处理对象都是信号数据。信号数据可以很⽅便的从数学上进⾏刻画和描述,可以直接作为特征输⼊到深度学习模型中,⽽这也是深度学习能够在图像处理和语⾳处理取得重⼤突破的重要原因之⼀。
⽬前主要流⾏的⽂本表⽰⽅法是词嵌⼊(词向量)分布式表⽰⽅法,⽬前已经被⼴泛应⽤于各项⾃然语⾔处理任务中。分布式表⽰⽅法主要基于分布式假说(distributional hypothesis,上下⽂相似的词,其语义也相似。该假说由 Harris 在 1954 年提出,并由 Firth 在 1957年进⼀步明确和完善)。
接下来需要界定⼏个概念:(参考来斯惟博⼠的毕业论⽂)
分布表⽰(distributional reprentation):分布(distributional)描述的是上下⽂的概率分布,因此⽤上下⽂描述语义的表⽰⽅法(基于分布假说的⽅法)都可以称作分布表⽰。与之相对的是形式语义表⽰。
菠菜丸子分布式表⽰(distributed reprentation):分布式(distributed)描述的是把信息分布式地存储在向量的各个维度中,与之相对的是局部表⽰(local reprentation),如词的独热表⽰(one-hot reprentation),在⾼维向量中只有⼀个维度描述了词的语义。⼀般来说,通过矩阵降维或神经⽹络降维可以将语义分散存储到向量的各个维度中,因此,这类⽅法得到的低维向量⼀般都可以称作分布式表⽰。
本⽂主要从原理介绍结合实验实践来介绍⽬前主流的Word2Vec,GloVe,Paragraph2vec,FastText和DSSM五种⽂本嵌⼊式⽅法(分布式表⽰⽅法),这⼏种⽅法分别从不同的⽂本粒度(⼦词、词、句、段落)探索了⽂本嵌⼊式表⽰⽅法。
2 相关⼯作
2.1 基于矩阵的分布表⽰
12生肖年份
较为经典的⽅法是基于矩阵的分布表⽰⽅法。基于矩阵的分布表⽰通常⼜称为分布语义模型,这类⽅法需要构建⼀个“词-上下⽂”矩阵,从矩阵中获取词的表⽰。这类⽅法具体可以分为三个步骤:
⼀、选取上下⽂。最常见的有三种⽅法:
第⼀种,将词所在的⽂档作为上下⽂,形成“词-⽂档”矩阵;
第⼆种,将词附近上下⽂中的各个词(如上下⽂窗⼝中的 5 个词)作为上下⽂,形成“词-词”矩阵;
第三种,将词附近上下⽂各词组成的 n 元词组(n-gram)作为上下⽂。在这三种⽅法中,“词-⽂档”矩阵⾮常稀疏,⽽“词-词”矩阵相对较为稠密,效果⼀般好于前者。“词-n 元词组”相对“词-词”矩阵保留了词序信息,建模更精确,但由于⽐前者更稀疏,实际效果不⼀定能超越前者。
⼆、确定矩阵中各元素的值。“词-上下⽂”共现矩阵根据其定义,⾥⾯各元素的值应为词与对应的上下⽂的共现次数。然⽽直接使⽤原始共现次数作为矩阵的值在⼤多数情况下效果并不好,因此研究⼈员提出了多种加权和平滑⽅法,最常⽤的有 tf-idf(词频-逆⽂档频)、PMI (点互信息)和直接取 log。
三、矩阵分解(可选)。在原始的“词-上下⽂”矩阵中,每个词表⽰为⼀个⾮常⾼维(维度是不同上下⽂的总个数)且⾮常稀疏的向量,使⽤降维技术可以将这⼀⾼维稀疏向量压缩成低维稠密向量。降维技术可以减少噪声带来的影响,但也可能损失⼀部分信息。最常⽤的分解技术包括奇异值分解(SVD)、⾮负矩阵分解(NMF)、典型关联分析(Canonical Correlation Analysis, CCA)、Hellinger
同学的漂亮妈妈PCA(HPCA)。
基于矩阵的分布表⽰在这些步骤的基础上,衍⽣出了若⼲不同⽅法,如经典的 LSA 就是使⽤“词-⽂档”矩阵, tf-idf 作为矩阵元素的值,并使⽤ SVD分解,得到词的低维向量表⽰。在这类⽅法中,最新的GloVe 模型就是借鉴了这种词共现矩阵的思想,后⾯会介绍该模型。 举⼀个“词-上下⽂矩阵”简单的例⼦。假设我们的语料库由三句话构成:
1→ I like deep learning.
2→ I like NLP.
新松恨不高千尺3→ I enjoy flying.
然后设置统计窗⼝⼤⼩为1,并采⽤对称窗⼝(考虑词左侧和右侧,⾮对称窗⼝则考虑⼀侧),可以
得到矩阵如图1所⽰:
竞选学生会主席演讲稿
图1
接下来,每⾏都可以作为⼀个单词的词向量了,或者更进⼀步⽤矩阵分解等的⽅法,得到词向量。
2.2 基于聚类的分布表⽰
基于聚类的分布表⽰⼜称作分布聚类(distributional clustering),这类⽅法通过聚类⼿段构建词与其上下⽂之间的关系。其中最经典的⽅法是布朗聚类(Brown clustering)。布朗聚类是⼀种层级聚类⽅法,聚类结果为每个词的多层类别体系。因此可以根据两个词的公共类别判断这两个词的语义相似度。 具体⽽⾔,布朗聚类需要最⼤化以下似然,其中 ci 为词 wi 对应的类别:
布朗聚类只考虑了相邻词之间的关系,也就是说,每个词只使⽤它的上⼀个词,作为上下⽂信息。除了布朗聚类以外,还有若⼲基于聚类的表⽰⽅法。由于这类⽅法不是本⽂关注的重点,在此不再赘述。
2.3 基于神经⽹络的分布式表⽰
基于神经⽹络的分布表⽰⼀般称为词向量、词嵌⼊(word embedding)或分布式表⽰(distributed reprentation)。该⽅法主要通过神经⽹络技术对上下⽂,以及上下⽂与⽬标词之间的关系进⾏建模。由于神经⽹络较为灵活,这类⽅法的最⼤优势在于可以表⽰复杂的上下⽂。
相较于基于矩阵的分布表⽰⽅法中,最常⽤的上下⽂是词。如果使⽤包含词序信息的 n-gram 作为上下⽂,当 n 增加时, n-gram 的总数会呈指数级增长,此时会遇到维数灾难问题。⽽神经⽹络在表⽰ n-gram 时,可以通过⼀些组合⽅式对 n 个词进⾏组合,参数个数仅以线性速度增长。
神经⽹络词向量模型与其它分布表⽰⽅法⼀样,均基于分布假说,核⼼依然是上下⽂的表⽰以及上下⽂与⽬标词之间的关系的建模。构建上下⽂与⽬标词之间的关系,最⾃然的⼀种思路就是使⽤语⾔模型。从历史上看,早期的词向量只是神经⽹络语⾔模型的副产品。如
bengio03年提出的nnlm,mikolov当年提出rnnlm,当时提出语⾔模型是对语⾔更好的建模,结果在训练的同时还得到了词向量,接着mikolov等⼈在词向量对于词的语义的表⽰进⾏了研究,如在2013的⼀篇⽂章中研究词向量空间中语义的表⽰,并发现了有趣的现象。
图2
如图2所⽰,通过Word2Vec学习得到的词向量在降维到⼆维平⾯上可以发现:man和woman在语义空间的相对位置与uncle和aunt、king和queen的相对位置是⼀致的,并且词的复数形式如kings和king的
相对位置与queens和queen的相对位置是⼀致的。
同时mikolov在13年另⼀篇⽂章对不同语⾔词向量的可视化发现通过词向量表⽰,不同语⾔相同语义的词在词向量空间中处于的位置差不多,从⽽进⼀步说明了词向量刻画词语义的合理性与有效性。图3所⽰为英语(左边)和西班⽛语(右边)分别通过Word2Vec训练得到的词向量在⼆维平⾯上的映射,分别选取了从1到5、猫狗等单词。可以看到不同语⾔,但是相同语义的单词在词向量空间中所处的相对位置极为相似。
图3
3 Word2Vec学习与实验
Word2Vec是⼀种基于神经⽹络的分布式表⽰⽅法(词向量,虽然模型只有⼀层,勉强算神经⽹络吧)。可以说Word2vec是mikolov等⼈在rnnlm的基础上探索词向量,从⽽设计的⼀个专门⽣成词向量的模型。值得注意的是,word2vec⽤到的模型都是lbl(log-bilinear language model)的。word2vec⽅法主要包括四个内容:cbow(continuous bag-of-words)模型、skip-gram(continuous skip-gram)模型,以及输出层的两种处理⽅法层次softmax(hs、hierarchical softmax)、以及负抽样(ng、negative sample)。
Word2Vec这部分的原理学习,推荐学习peghoty⼤神的《》⼀⽂。
3.1 CBOW和Skip-gram模型
如图4所⽰,左边是cbow右边是skip-gram,⼀句话,cbow是依据⽬标词周围单词猜测⽬标词,skip-gram是依据当前词猜测周围有啥词,很好理解。虽然表⾯上word2vec与矩阵的算法不同,但这种对上下⽂环境的预测,本质上也是⼀种对共现矩阵统计特征的学习,如后⾯介绍glove时,来斯惟等⼈在论⽂中证明了glove的损失函数实际上与SG(skip-gram)的是⼀样的。
插座国标
图4
Cbow训练过程就是将⼀个窗⼝内的所有单词向量叠加(后期的算法将叠加后取了平均),输出到映射层(不要紧张,映射层意思就是中间层,离神经⽹络的隐藏层还差点意思),映射层再依据层次softmax或者负抽样获得输出,然后是求残差传播blabla。。。
Skip-gram训练过程就是将当前单词直接输出到映射层,然后再依据层次softmax或者负抽样得到输出,再求残差传播blabla。。。
这时候⼩伙伴们可能要问了,这也是我很长时间不理解的地⽅,直到看别⼈解析源代码时提到参数初始化时,才彻底理解了这个问题。⼀开始word2vec汇总统计语料中出现的所有单词,做了⼀个词汇表,然后给每个单词随机赋予初始值向量(每个维度值在⼀个指定范围内,其实获得词向量的这个过程有点像我们整理玩具箱⾥的玩具⼀样,先端起来把所有玩具撒在地摊上,这时每个玩具所在的位置都是随机的,然后再将玩具放到玩具箱中它应该放置的位置上)。
3.2 层次Softmax
然后就是理解⼀下层次softmax,如图5所⽰。
图5
我们看到从映射层到输出有⼀颗⼆叉树,他的根节点就是映射层对应的输出,叶⼦节点就是该语料所有的单词,依据单词出现的频率以及⼀个计算公式,为每个单词赋⼀个权重,然后构成哈夫曼树。
五官立体
从映射层出来的向量从根节点开始,利⽤该节点的参数θ,以及sigmoid的想法确定接下来往左节点⾛,还是往右节点⾛,上图所⽰红⾊路径即为⼀次路径的⾏⾛。但其实层次softmax要计算所有节点,⼀直计算到叶⼦节点,这时候来⼀个softmax,便可得到每个单词的概率。
当然要使我们⽬标单词的概率最⼤啊,所以就可以计算残差,传播,balabala。。。
3.3 负抽样(Negative Sampling)
负抽样不采⽤复杂的Huffman树,⽽是利⽤相对简单的随机负采样,能⼤幅提⾼性能,因⽽可以作为层次Softmax的⼀种替代。
Word2Vec这部分的原理学习,推荐学习peghoty⼤神的《》⼀⽂。
3.4 ⽬标函数
CBOW
Skip-gram
计算:
sigmoid:
华表简笔画
例如:
然后:
Word2Vec这部分的原理学习,推荐学习peghoty⼤神的《》⼀⽂。
3.5 实验
3.5.1 C实现的Word2Vec实验
如图6所⽰是从google上下载下来的c实现的Word2Vec的所有⽂件,可以看到⾥⾯有⼏个demo脚本可以⽤来演⽰。