NLP相关任务
- 自动摘要
- 指代消解 小明放学了,妈妈去接【他】
- 机器翻译 小心地滑->Slide carefully
- 词性标注 heat(v.) water(n.) in(p.) a(det.) pot(n.)
- 分词(中文,日文等) 大水沟/很/难/过
- 主题识别
- 文本分类
NLP处理方法
- 传统:基于规则
- 现代:基于统计机器学习
- HMM,CRF,SVM,LDA,CNN …
- “规则”隐含在模型参数里
词编码需要保证词的相似性
人在看到一个词时,会想到与它相似的词。
如果只是给每个词设置一个索引下标来对词进行编码,无法体现词与词之间的相关性。
Nearest words to frog:
frogs、toad、litoria、leptodactylidae、rana、lizard、eleutherodactylus
简单 词/短语 翻译
向量空间分布的相似性
向量空间子结构
希望能够捕捉到词与词之间的关系
最终目标:词向量表示作为机器学习、特别是深度学习的输入和表示空间
在深度学习中,数据决定了结果的上限,算法只能决定能在多大程度上逼近这个上限。
在计算机中表示一个词
在英语中 nltk 库 ,包含此类词典。
通过专家根据背景知识来人为的构造。
存在问题:
- 不能分辨细节的差别
- 需要大量人为劳动
- 有主观性
- 无法发现新词
- 难以精确计算词之间的相似性
离散表示:One-hot 表示
语料库:
John likes to watch movies. Mary likes too.
John also likes to watch football games.
词典:
{“John”:1,“likes”:2,“to”:3,“watch”:4,“movies”:5,“also”:6,“football”:7,“games”:8,“Mary”:9,“too”:10}
One-hot 表示
John:[1,0,0,0,0,0,0,0,0,0]
likes:[0,1,0,0,0,0,0,0,0,0]
…
too:[0,0,0,0,0,0,0,0,0,1]
- 词典包含10个单词,每个单词有唯一索引
- 在词典中的顺序和在句子中的顺序没有关联
离散表示:Bag of Words
- 文档的向量表示可以直接将各词的词向量表示加和
John likes to watch movies. Mary likes too. ->[1,2,1,1,1,0,0,0,1,1]
John also likes to watch football games. ->[1,1,1,1,0,1,1,1,0,0]
句子的向量表示为,对应词典,每个位置上的词在这个句子中所出现的次数。
每个词是One-hot表示,整个句子就是 Bag of Words 表示形式。
丢失了词语在句子中的前后顺序信息。
- TF-IDF (Term Frequency-Inverse Document Frequency)
该词在整个语料库中出现的次数越多,IDF值越小,表示该词越不重要。
[0.693, 1.386, 0.693, 0.693, 1.099, 0, 0, 0, 0.693, 0.693]
离散表示:语言模型 Bi-gram 和 N-gram
离散表示的问题
- 无法衡量词向量之间的关系
- 太稀疏,很难捕捉文本的含义
- 词表维度随着语料库增长膨胀
- n-gram 次序列随语料库膨胀更快
分布式表示(Distributed representation)
Distributional Representation是从分布式假设(即如果两个词的上下文相似,那么这两个词也是相似的)的角度,利用共生矩阵来获取词的语义表示,可以看成是一类获取词表示的方法。这里的“分布”带有统计上分布的意思。我们可以构建一个大小为W×C的共现矩阵F,其中W是词典大小,C是上下文数量。上下文的类型可以为相邻词、所在句子或所在的文档等。共现矩阵的每一行可以看作对应词的向量表示。基于共现矩阵,有很多方法来得到连续的词表示,比如潜在语义分析模型(Latent Semantic Analysis, LSA)、潜在狄利克雷分配模型(Latent Dirichlet Allocation,LDA)、随机索引(random indexing)等。
Distributed Representation中的distributed 没有统计上的“分布”含义,而是“分散”、“分配”的意思。一段文本的语义分散在一个低维空间的不同维度上,相当于将不同的文本分散到空间中不用的区域。Distributed Representation是文本的一种表示形式,具体为稠密、低维、连续的向量。向量的每一维都表示文本的某种潜在的语法或语义特征。这种“分散式表示”只要在低维的空间中能够区分出两个词的不同就够了。不一定非得要求意义相近的词距离也相近。
Distributional Representation指的是一类获取文本表示的方法,而Distributed Representation指的是文本表示的形式,就是低维、稠密的连续向量。这两个并不对立。比如Skip-Gram、CBOW和glove等模型得到词向量,即是Distributional Representation,又是Distributed Representation。
用一个词附近的其他词来表示该词。被称为现代统计自然语言处理中最有创见的想法之一。
You shall know a word by the company it keeps. (J.R.Fitth 1957:11)
共现矩阵(Cocurrence matrix)
Word-Document 的共现矩阵主要用于发现主题(topic),用于主题模型,如LSA(Latent Semantic Analysis)
局域窗 中的 Word-Word 共现矩阵 可以挖掘语法和语义信息
- I like deep learning.
- I like NLP.
- I enjoy flying.
此处 window length 设为 1 (一般设为 5~10)
使用对称的窗函数(左右 window length 都为1)
这三句话的共现矩阵如下:
矩阵中的值为语料中 每个词局域窗范围内词组合出现的次数。
将共现矩阵行(列)作为词向量,存在的问题:
- 向量维数随着词典大小线性增长
- 存储整个词典的空间消耗非常大
- 一些模型如文本分类模型会面临稀疏性问题
- 模型会欠稳定(新加预料后向量就变了)
所以我们需要构造低维稠密向量作为词的分布式表示(25~1000维)
SVD(奇异值分解) 降维
最直接的想法:用SVD对共现矩阵向量做降维。
import numpy as np
import matplotlib.pyplot as plt la=np.linalg
words=["I","like","enjoy","deep","learning","NLP","flying","."]
X=np.array([[0,2,1,0,0,0,0,0],[2,0,0,1,0,1,0,0],[1,0,0,0,0,0,1,0],[0,1,0,0,1,0,0,0],[0,0,0,1,0,0,0,1],[0,1,0,0,0,0,0,1],[0,0,1,0,0,0,0,1],[0,0,0,0,1,1,1,0]
])U,s,Vh=la.svd(X,full_matrices=False)plt.axis([-0.8,0.2,-0.8,0.8]) for i in range(len(words)):plt.text(U[i,0],U[i,1],words[i])
plt.show()
可以看出,I 与 like 和 enjoy 的距离相近。
SVD降维存在的问题:
- 计算量随语料库和词典增长膨胀太快,对 X(n,n) 维的矩阵,计算量 O ( n 3 ) O(n^3) O(n3)。而对大型的语料库,n~400k,语料库大小 1~60B token。
- 难以为词典中新加入的词分配词向量
- 与其他深度学习模型框架差异大
NNLM(Neural Network Language model)
直接从语言模型出发,将模型最优化过程转化为求词向量表示的过程。
根据前 n-1 个单词,预测第t个位置单词的概率。
使用了非对称的前向窗函数,窗长度为 n-1
滑动窗口遍历整个语料库求和,计算量正比于语料库大小
概率P满足归一化条件,这样不同位置t处的概率才能相加,即
用神经网络来实现概率P
输出层是Softmax,一个线性的多分类器
中间只有一个隐藏层
输入层每个输入节点是每个单词的 one-hot 向量表示,用n-1个词预测下一个词,有 n-1 个输入节点。
与 投影矩阵 C 相乘,得到该词的稠密D维词向量表示。
如 D 为500 , 投影矩阵 C 为 500*80000 维矩阵。 语料库中有80000个词。
一个单词的one-hot 表示是 80000*1 的向量。 (只有一个位置上为1,其他都为0)
投影矩阵C * 词向量=一个500*1 维的向量,即为该词的稠密词向量表示。
其实整个过程就是一个look-up 的过程,在投影矩阵(相当于一个词典)中得到对应词的向量表示。
将每个单词的词向量进行拼接,放入有一个隐藏层的人工神经网络,隐藏层神经元个数一般为300或500,激活函数为 tanh 双曲正切 ,softmax是线性分类器,得到 词典个数维的概率向量,每个位置表示是这个单词的概率,与已知的输出计算交叉熵(Cross Entropy)损失,不断训练整个模型。
起始状态的 投影矩阵C 的数值是随机初始化的,通过神经网络的不断学习最终得到词典。
各层权重最优化:BP+SGD
输入层为N个单词的向量,每个单词映射为D维的词向量,隐藏层规模为H,输出层规模为V,则每个训练样本的计算复杂度:ND+NDH+HV
一个简单模型在大数据量上的表现比复杂模型在少数据量上的表现会好。
word2vec:CBOW (连续词袋)
上图第一个目标函数,应该为连乘的形式。转换为log 后变成连加。
去掉隐藏层,所以也没有激活函数(此模型实际不属于深度学习)
由于最后输出词典中每个词的概率,输出向量有80000维(词典长度),映射层为各个单词向量相加,为500维,则从映射层到输出层需要一个500*80000维的权重,计算量过大,所以采用以下方法优化。
层次Softmax,完成从映射层到输出层
W=“足球” 时的相关记号示意图
使用 Huffman Tree 来编码输出层的词典
只需要计算路径上所有非叶子节点词向量的贡献即可
计算量降为树的深度 V=> l o g 2 ( V ) log_2(V) log2(V)
此时中间的单词为 w(t) ,而映射层输入为 pro(t)=v(w(t-2))+v(w(t-1))+v(w(t+1))+v(w(t+2))
假设此时的单词为“足球”,即 w(t)=“足球” ,则其Huffman码可知为 d(t)=“1001” ,那么根据Huffman码可知,从根节点到叶节点的路径为 “左右右左”,即从根节点开始,先往左拐,再往右拐2次,最后再左拐。
既然知道了路径,那么就按照路径从上往下依次修正路径上各节点的中间向量。在第一个节点,根据节点的中间向量 Θ(t,1) 和 pro(t) 进行逻辑分类。如果分类结果显示为0,则表示分类错误(应该向左拐,即分类到1),则要对 Θ(t,1) 进行修正,并记录误差量。
接下来,处理完第一个节点之后,开始处理第二个节点。方法类似,修正 Θ(t,2) ,并累加误差量。接下来的节点都以此类推。
在处理完所有节点,达到叶节点之后,根据之前累计的误差来修正词向量 v(w(t))。
这样,一个词w(t)的处理流程就结束了。如果一个文本中有N个词,则需要将上述过程在重复N遍,从w(0)~w(N-1)。
负例采样
工业界用负例采样比较多。
从映射层到输出层,对负样本进行负例采用,减小权重矩阵大小,和输出概率向量大小。
根据每个单词出现的频度,划分这条线段。看随机产生的整数,属于哪个词的线段,就取出这个词。
word2vec:Skip-Gram 模型
如果语料库较大,用Skip-Gram比CBOW好。
word2vec:存在问题
- 对每个 local context window 单独训练,没有利用包含在 global co-currence 矩阵中的统计信息。
- 对多义词无法很好的表示和处理,因为使用了唯一的词向量。
词嵌入可视化:
公司——CEO
词向
比较级和最高级
词嵌入效果评估:
1、词类比任务
如:
“Athens is to Greece as Berlin is to____?”
“Bigger is to Big as Greater is to____?”
2、词相似度任务
3、作为特征用于CRF实体识别
GloVe与Word2Vec对比
GloVe随着迭代次数增加,精度提升
Word2Vec未使用类似迭代次数的Epoch,用Negative Samples模拟
Glove 相比 word2vec 可以考虑全局的信息,但深度学习还是用 word2vec 比较多,它只是神经网络的一层,会随着整个模型的训练而调整。
总结
-
离散表示
-
One-hot representation ,Bag of words Unigram 语言模型
-
N-gram 词向量表示和语言模型
-
共现矩阵的行(列)向量作为词向量
-
分布式连续表示
-
共现矩阵的SVD降维的低维词向量表示
-
Word2Vec :CBOW Model
-
Word2Vec:Skip-Gram Model
工具:google word2vec
❖地址
https://code.google.com/archive/p/word2vec/
墙内用户请戳https://github.com/dav/word2vec
❖ 安装步骤
git clone https://github.com/dav/word2vec
cd word2vec/src
Make
试试./demo-word.sh 和./demo-phrases.sh
python常用的库 :gensim
Word2vec+CNN做文本分类
论文详见《Convolutional Neural Networks for Sentence Classification》
http://arxiv.org/abs/1408.5882
Theano完成的代码版本:
https://github.com/yoonkim/CNN_sentence
TensorFlow改写的代码版本:
https://github.com/dennybritz/cnn-text-classification-tf
添加 分词和 中文词向量映射之后,可用于中文文本分类(情感分析)
维基百科词向量构建:https://www.zybuluo.com/hanxiaoyang/note/472184
搜狗全网新闻语料地址 :http://www.sogou.com/labs/resource/ca.php
sense2vec:
word2vec模型的问题在于词语的多义性。比如duck这个单词常见的含义有
水禽或者下蹲,但对于 word2vec 模型来说,它倾向于将所有概念做归一化
平滑处理,得到一个最终的表现形式。
我们结合上下文和标签,会有更好的处理结果
用Spacy和word2vec结合,完成sense2vec
https://github.com/explosion/sense2vec
doc2vec:
Doc2vec是基于Word2vec的基础上发展而来的方法,它可以将一段句子表征为实数值向量。
http://cs.stanford.edu/~quocle/paragraph_vector.pdf
http://www.dataguru.cn/article-9478-1.html
http://blog.csdn.net/lenbow/article/details/52120230