NLP(Natural Language Processing)
NLP主要是关注计算机和人类(自然)语言之间的相互作用的领域。如果要想实现人机间自然语言通信意味着要使计算机既能理解自然语言文本的意义,也能以自然语言文本来表达给定的意图、思想等。前者称为自然语言理解,后者称为自然语言生成,这也是NLP的两大任务。
但处理它的困难之处在于自然语言是一种符号,出现的理由是为了作为一种方便人类进行高效交流的工具,但,想要高效免不了会进行省略,即说话人之间交流可能只说一小部分话,然后剩下的部分是由听话人按自己的世界观进行补全。另外语言和句法中本身存在模糊不清,同一句话可能有多个意义。语义可能与顺序和指代词有关,而且某些语言就人类角度还带有深意等等等…
语言模型(Language Model)
想要量化语言,首先需要建模。语言模型就是用来衡量一句话多大程度是人话的模型(是否通顺,符合语法句法),理论上可以直接把整个句子放进模型然后预测这个句子S是否是人话,但这样训练量大,且很难学习到句子的内部特征。那么可以使用Chain Rule,把句子中每个词的联合概率表示,也可以表示成多个条件概率的乘积。LM分为Unigram,Bigram(first order markov assumption),N-gram。 U n i g r a m , P ( S ) = P ( w 1 , w 2 , . . . , w n ) = P ( w 1 ) P ( w 2 ) P ( w 3 ) . . . P ( w n ) Unigram,P(S)=P(w_1,w_2,...,w_n)=P(w_1)P(w_2)P(w_3)...P(w_n) Unigram,P(S)=P(w1,w2,...,wn)=P(w1)P(w2)P(w3)...P(wn) B i g r a m , P ( S ) = P ( w 1 , w 2 , . . . , w n ) = P ( w 1 ) P ( w 2 ∣ w 1 ) P ( w 3 ∣ w 2 ) . . . P ( w n ∣ w n − 1 ) Bigram,P(S)=P(w_1,w_2,...,w_n)=P(w_1)P(w_2|w_1)P(w_3|w_2)...P(w_n|w_{n-1}) Bigram,P(S)=P(w1,w2,...,wn)=P(w1)P(w2∣w1)P(w3∣w2)...P(wn∣wn−1) N − g r a m , P ( S ) = P ( w 1 , w 2 , . . . , w n ) = P ( w 1 ) P ( w 2 ∣ w 1 ) P ( w 3 ∣ w 1 , w 2 ) . . . P ( w n ∣ w 1 , w 2 , . . . , w n − 1 ) N-gram,P(S)=P(w_1,w_2,...,w_n)=P(w_1)P(w_2|w_1)P(w_3|w_1,w_2)...P(w_n|w_1,w_2,...,w_{n-1}) N−gram,P(S)=P(w1,w2,...,wn)=P(w1)P(w2∣w1)P(w3∣w1,w2)...P(wn∣w1,w2,...,wn−1) L = ∑ w ∈ C l o g P ( w ∣ c o n t e x t ( w ) ) , C 为 w 的 映 射 L=\sum_{w\in C} logP(w|context(w)),C为w的映射 L=w∈C∑logP(w∣context(w)),C为w的映射
其中Estimating Probability的P(Wn) = 词汇Wn出现次数 / 语料库所有词汇数量V。
ungram model是最简单的,不考虑语言逻辑,如“今天 下雪 了”和“了 下雪 今天”的概率显然不应该是一样的。Bigram model在随机的基础上,会大概率选取关联概率最大的单词,因此优于unigram。N-gram,在有大量的语料库的基础上,可以训练。
如何评估语言模型?
计算P的概率便可以判断了,所以准确率,recall也是可以使用的。但是在LM一般使用句子的混乱度来判断:
P e r p l e x i t y = 2 ( − x ) Perplexity = 2^{(-x)} Perplexity=2(−x) x = l o g P ( w 1 ) + l o g P ( w 2 ∣ w 1 ) . . . N x=\frac{logP(w_1)+logP(w_2|w_1)...}{N} x=NlogP(w1)+logP(w2∣w1)...x : average log likelihood。一般来说它越小越好,N-gram考虑了很多的情况时,Perplexity是最小的。
如何处理语料库没有的情况?
如果出现了语料库没有词汇,将会导致概率连乘为0的情况。Smoothing的方法有:
N-gram 语言模型缺点
简而言之,N-gram 模型就是用 P ( w t ∣ w t − n + 1 , … , w t − 1 ) P(w_t | w_{t-n+1}, …, w_{t-1}) P(wt∣wt−n+1,…,wt−1)来模拟上述公式的方法,式子中的N比那时N-gram的来历。当N=1的时候,公式会退化变成:
p ( w t ∣ C o n t e x t ) = p ( w t ) = N w t N p(w_t|Context)=p(w_t)=\frac{N_{w_t}}{N} p(wt∣Context)=p(wt)=NNwt
它也被称为一元语言模型,或者上下文无关语言模型,即不考虑该词所对应的上下文环境,仅考虑当前词本身的概率,那么通过计算词频就可以达成目标了。
但N-gram 语言模型也存在一些问题:
神经网络语言模型(Neural Network Language Model,NNLM)
其实处理N-gram的问题,不可以用one-hot处理词后再进行相似度计算?词数太多太稀疏?矩阵分解可以解决。词的权重可以利用TF * IDF来计算,其中TF表示词频,即一个词在这篇文本中出现的频率;IDF表示逆文档频率,即一个词在所有文本中出现的频率倒数。
但是,在数据集如何足够的情况下…请上深度学习,意在求解某个抽象过的特征向量来代表某个词(这也是主要区别,一个词就是词,另一个把词变成了向量,语义更丰富,而且每个句子、短语和逻辑表述都是向量,然后再神经网络负责合并),特别在是单词在句子语境中,应该通过单词的同伴来知道它的意思,在文本中理解它的意思。不过如何求解其中的参数,使其能够根据context上下文来进行理解句子的可能尝试呢?NNLM模型便如下图:
尝试用神经网络方法求解的一般思路是:
θ + ϵ ∂ l o g p ( w t ∣ w t − 1 , … , w t − n + 2 , w t − n + 1 ) ∂ θ → θ \theta + \epsilon \frac{\partial log p(w_t | w_{t-1},\dots,w_{t-n+2},w_{t-n+1})}{\partial \theta} \to \theta θ+ϵ∂θ∂logp(wt∣wt−1,…,wt−n+2,wt−n+1)→θ
然后结合具体NNLM的模型图,它的处理细节是先假设每个单词的输入共享一个词向量(其实这是副产物,它的出现还是为了预测句子的),于是可以得到每个词向量,然后先nn一层,再把这个输入和原词向量拼接后在nn,以预测下一个词。网络训练完成后,也就得到这样的词向量,完成了word embedding。
word2vec
Word2Vec是NNLM的升级版,基本的网络结构很像,只是训练方法不太一样。主要有两种形式,通过这两种形式,最后得到每个词的词向量(副产物):
###关于word2vec的理论细节推导强烈推荐《word2vec中的数学原理详解》,下面只整理一些个人的想法。
(w(t)代表当前词语位于句子的位置t,窗口大小为5,共同构成上下文)
首先这两者与NNLM模型的不同在于,一是没有NNLM的隐层(据说是因为隐层会使矩阵运算变很多),二是输入层单词经过映射矩阵得到的D维词向量累加而不是拼接构成映射层,三是使用了哈夫曼非线性。
CBOW,可以看成由当前词汇到预测其他相关词汇的多分类问题,但是对于最后的输出进行多分类softmax有千万级的词汇映射,显然不可能。所以对于CBOW的优化过程主要是Hierarchical Softmax,通过多个二叉树–二分类来曲线救国。具体的过程是先累加向量(向量的相加将变成路径),然后做n个逻辑回归来预测哈夫曼树(根据词频建立的,其实先DNN但是参数多了才哈夫曼的),这就是hierarchical softmax优化,以二叉树的思想来得到概率,最后所建立二叉树的每个非叶子节点相当于神经元。
Skig-Gram,逆转因果关系,其实是给定单词输出跟单词联系可能紧密的词。但是同样会面对权重矩阵太大的问题,所以引出了另一个优化为:
下图是具体流程:从左到右先是one-hot向量,乘center word的 W 找到词向量,乘另一个context word的矩阵 W’ 得到对每个词语的“相似度”(内积能代表相关性)以做到预测上下文其他词汇的效果,然后多个结果进行softmax得到概率,再与label对比计算损失。(显然这个矩阵会很大,所以具体实现需要结合上述的优化以达到近似的效果)
J t ( θ ) = log σ ( u o T v c ) + ∑ i = 1 k E j ∼ P ( w ) [ log σ ( − u j T v c ) ] J_t(\theta) = \log \sigma\left(u_o^Tv_c\right)+\sum_{i=1}^k\mathbb{E}_{j \sim P(w)}\left [\log\sigma \left(-u^T_jv_c\right) \right] Jt(θ)=logσ(uoTvc)+i=1∑kEj∼P(w)[logσ(−ujTvc)]
t是窗口,k是采样个数。
#先分词,比如结巴分词
import jieba
f1 =open("test.txt")
f2 =open("retrun.txt", 'a')
lines =f1.readlines()
for line in lines:
line.replace('\t', '').replace('\n', '').replace(' ','')
seg_list = jieba.cut(line, cut_all=False)
f2.write(" ".join(seg_list))
f1.close()
#gensim,从文档中自动提取语义主题的nlp必备神库
from gensim.modelsimport word2vec
sentences =word2vec.Text8Corpus("retrun.txt")
#skip-gram,默认window=5
model =word2vec.Word2Vec(sentences, size=200)
print(model)
#1计算相似度
y1 = model.similarity(wordA, wordB)
#2计算某个词的相关词列表
y2 = model.most_similar(wordA, topn=20)
#3不合群的词
y4 =model.doesnt_match(words.split())
model.save()
负采样NEG过程
GloVe
于是Glove开始结合两者,使用全局的信息(共线矩阵),也就是多个窗口进行更新。
J ( θ ) = 1 2 ∑ i , j = 1 W f ( P i j ) ( u i T v j − log P i j ) 2 J(\theta)=\frac{1}{2}\sum_{i,j=1}^W f(P_{ij})\left(u_i^Tv_j-\log P_{ij}\right)^2 J(θ)=21i,j=1∑Wf(Pij)(uiTvj−logPij)2
Pij是两个词共现的频次,f是一个max函数,小于某个值时如0.5:y=2x,此后恒为1。由于u 和v都能够捕捉到共现,所以X=U+V
Representation Learning
表示学习是深度学习领域的一个概念,是学习数据表示的技术的集合,用于将现实世界中的数据转化成能够被计算机高效处理的形式。与之相对应,在机器学习领域,数据表示主要通过特征工程(feature engineering)手动实现,依赖特征的选择,而在深度学习则是自动获取的,依赖大量的数据。而将词表示为一个向量,也属于表示学习。从概念上,它是指把一个维数为所有“词”数量的高维空间嵌入到一个维数低的连续向量空间中,现有的方法主要有:
Distributed方法自然有很多,主要基于Distributional hypothesis,即满足具有相同上下文的词语,应该具有相似的语义。
基于此的常规主要有以下几种方法:
目前的词嵌入用深度学习方法会更加的普遍,如上图中的一些模型。
softma的常数不变性
s o f t m a x ( x ) = s o f t m a x ( x + c ) softmax(x) = softmax(x + c) softmax(x)=softmax(x+c)
即softmax不受加入常数的影响:
( s o f t m a x ( x + c ) ) i = e x i + c ∑ j e x j + c = e x i × e c e c × ∑ j e x j = e x i × e c e c × ∑ j e x j = ( s o f t m a x ( x ) ) i (softmax(x + c))_{i} = \frac{e^{x_{i} + c}}{\sum_{j} e^{x_{j} + c}} = \frac{e^{x_{i}} \times e^{c}}{e^{c} \times \sum_{j} e^{x_{j}}} \\ = \frac{e^{x_{i}} \times \cancel{e^{c}}}{\cancel{e^{c}} \times \sum_{j} e^{x_{j}}} = (softmax(x))_{i} (softmax(x+c))i=∑jexj+cexi+c=ec×∑jexjexi×ec=ec ×∑jexjexi×ec =(softmax(x))i
这种特性能在,即使两个数都很大比如 1000与 1001,但是其结果与 1和2的结果相同,那么在计算时只需要关注数字之间的差,而不是差占的比例。