第9章 自然语言处理
- 发展历程
- 在自然语言处理研究的早期,人们试图整理出关于自然语言的语法,并根据这些语法去理解和生成句子
- 从20世纪80年代起,随着硬件计算能力的增强和大型语料库的出现,使用统计方法对语言进行概率建模的方式开始变成主流
- 从2010年起,基于循环神经网络的方法在许多自然语言处理的问题上超越了传统的统计模型
9.1 语言模型的背景知识
9.1.1 语言模型简介
语言模型简介
- 假设一门语言中所有可能的句子服从某一个概率分布,每个句子出现的概率加起来为1,那么语言模型的任务就是预测每个句子在语言中出现的概率
- 把句子看成单词的序列,语言模型可以表示为一个计算
p(w1,w2,w3,...,wm)
的模型 - 语言模型仅仅对句子出现的概率进行建模,并不尝试“理解”句子的内容含义
语言模型应用
- 很多生成自然语言文本的应用都依赖语言模型来优化输出文本的流畅性
- 生成的句子在语言模型中的概率越高,说明其越有可能是一个流畅、自然的句子
- 神经网络机器翻译的Seq2Seq模型可以看作是一个条件语言模型(Conditional Language Model),它相当于是在给定输入的情况下对目标语言的所有句子估算概率,并选择其中概率最大的句子作为输出
- 很多生成自然语言文本的应用都依赖语言模型来优化输出文本的流畅性
如何计算一个句子的概率
- 一个句子可以被看成一个单词序列
S = (w1, w2, w3, w4, ... wm)
- 其中
m
代表句子的长度
- 其中
- 它的概率可以表示为:
p(S) = p(w1, w2, w3, w4, ... wm) = p(w1) * p(w2 | w1) * p(w3 | w1, w2)...p(wm | w1, w2, w3,..., wm-1)
- 其中
p(wm | w1, w2, w3,..., wm-1)
表示,已知前m-1个单词时,第m个单词为wm的条件概率
- 其中
- 一个句子可以被看成一个单词序列
然而
- 任何一门语言的词汇量都很大,词汇的组合更是不计其数
- 假设一门语言的词汇量为V,如果要将
p(wm | w1, w2, w3,..., wm-1)
的所有参数保存在一个模型中,则需要pow(v, m)
个参数,数量太多
n-gram
- 为了控制参数的数量,n-gram模型做了一个有限历史假设:当前单词的出现概率仅仅与前面的
n-1
个单词相关 - 公式如下
- n-gram模型中的n指的是当前单词依赖它前面的单词的个数
- 通常n可以取1、2、3、4,其中n取1、2、3时分别称为unigram、bigram、trigram
- 假设某种语言的单词表大小为V,那么n-gram模型需要估计的不同参数数量为O(pow(v, n))量级
- 当n越大时,n-gram模型在理论上越准确,但也越复杂,需要的计算量和训练语料数据量也越大
- n-gram模型的参数一般采用最大似然估计(Maximum Likelihood Estimation, MLE)方法计算
- 训练语料的规模越大,参数估计的结果越可靠
- 但即使训练数据的规模非常大时,还是有许多单词序列在训练语料中不会出现,这就导致许多参数为0,为了避免因为乘以0而导致整个句子概率为0,使用最大似然估计的方法时需要加入平滑避免参数取值为0
- 为了控制参数的数量,n-gram模型做了一个有限历史假设:当前单词的出现概率仅仅与前面的
9.1.2 语言模型的评价方法—–复杂度(perplexity)
复杂度简介(perplexity)
- 语言模型效果好坏的常用评价指标是复杂度(perplexity)
- 在一个测试集上得到的perplexity越低,说明建模的效果越好
- 复杂度计算公式
- perplexity值刻画的是语言模型预测一个语言样本的能力
- 比如,已知(w1, w2, w3,…, wm)这句话会出现在语料库中,那么通过语言模型计算得到的这句话的概率越高,说明语言模型对这个语料库拟合的越好
perplexity的理解
- perplexity实际上计算每一个单词得到的概率倒数的几何平均
- perplexity可以理解为模型预测下一个词时的平均可选择数量
- 目前在PTB数据集上最好的语言模型perplexity为47.7,就是在平均情况下,该模型预测下一个词时,有47.7个词等可能地可以作为下一个词的合理选择
perplexity与交叉熵
- 交叉熵(Cross Entropy)用来描述两个概率分布之间的一种距离
- 在数学上log perplexity可以看作真实分布与预测分布之间的交叉熵
- 即每个位置上单词的真实分布与模型的预测分布之间的交叉熵
TensorFlow提供了两个方便计算交叉熵的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
import tensorflow as tf # 假设词汇表的大小为3,语料包含两个单词"2 0" word_labels = tf.constant([2, 0]) # 假设模型对两个单词预测时,产生的logit分别为[2.0, -1.0, 3.0]和[1.0, 0.0, -0.5] # 注意这里的logit不是概率,因此它们不是0.0-1.0之间的数字 # 如需要计算概率,则需要调用prob = tf.nn.softmax(logits) # 但这里计算交叉熵的函数直接输入logits即可 predict_logits = tf.constant([[2.0, -1.0, 3.0], [1.0, 0.0, -0.5]]) # 使用sparse_softmax_cross_entropy_with_logits函数计算交叉熵,即log perplexity的值 loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=word_labels, logits=predict_logits) # 计算perplexity损失的值 sess = tf.Session() print(sess.run(loss)) ''' [0.32656264 0.4643688 ] ''' # softmax_cross_entropy_with_logits与上面的函数类似,但是需要将预测目标以概率分布的形式给出 word_prob_distribution = tf.constant([[0.0, 0.0, 1.0], [1.0, 0.0, 0.0]]) loss = tf.nn.softmax_cross_entropy_with_lo