摘要 : [自然语言处理] [基于规则] [基于统计] [统计语言模型] [马尔科夫] [分词]
自然语言处理--基于规则
人类对于自然语言的处理在最开始的时候走了一大段的弯路,甚至耗尽了无数人的一生,那就是基于规则的处理方式;
很自然的人们想到了让计算机实现人类学习语言的方式来处理自然语言,让机器来理解自然语言,然后处理,也就是说计算机需要做到以下两点:
- 分析语句
- 获取语义
之所以当时的研究方向如此有以下几个原因:
- 让计算机做跟人做一样的事这个要求在人看来,第一想法就是像人一样学习理解自然语言;
- 当时的学术界在传统语言研究上非常系统以及成熟;
- 语法规则,词性,构词法等这些规则更容易转换成代码;
自然语言处理:研究--应用依赖关系图:
- 应用层 [语音识别] [机器翻译] [自动问答] [自动摘要]
- 认知层 [自然语言理解]
- 基础层 [句法分析] [语义分析]
例子
基于规则如何理解下面这句话:
徐志摩喜欢林徽因
- 句子 -> 主语谓语句号;
- 主语 -> 名词;
- 谓语 -> 动词 / 名词短语;
- 名词短语 -> 名词;
- 名词 -> 徐志摩;
- 动词 -> 喜欢;
- 名词 -> 林徽因;
- 句号 -> .;
局限
- 规则数量不可控:基于规则的处理方法会将一个句子拆分成一棵语法分析树,而当句子变得复杂时,这颗树会迅速变得很大,以至于当我们需要使用规则覆盖20%的语句时,就至少需要几万条规则,而且如果我们想要覆盖其他语句,甚至会达到每一条语句都需要增加一个规则去适应,更麻烦的是这些规则有可能是互相矛盾的,那么为了解决这个矛盾还需要添加其他附加条件到规则中;
- 词义,上下文相关性:即便能够给出使用所有语句的规则,计算机也很难准确分析每句话,这是因为在语言的发展过程中,逐步发展出了语义以及上下文相关性,而计算机的程序语言被设计成上下文无关性,相对于自然语言来说更加简单(上下文无关的计算复杂度是语句长度的2次方,而上下文相关的计算复杂度则是语句长度的6次方,因此在语句长度增加后,基于规则的处理开始寸步难行);
自然语言处理--基于统计
最初使用基于统计的方法来进行自然语言处理并没有想要处理所有问题,而只是想要解决语音识别问题,也确实将语音识别的准确度提升到90%,将识别单词数提高到了几万个,但是仍存在几个问题使得自然语言处理仍处于规则与统计对立的状态:
- 没有足够强大的模型:当时的核心模型是通信系统+隐含马尔可夫模型,这种方式在处理输入输出都是一维符号序列时效果很好,这也是语音识别和词性分析获得成功的原因,但是在后面的句法分析(输入一个句子,输出二维的语法分析树)和机器翻译(虽然输入输出都是一维,但是顺序有很大变化)就不再适用了;
- 没有足够的统计数据;
当然这一切都在计算机的计算能力以及统计数据量的不断增多后得到了解决,基于统计的自然语言处理方法在数学模型上和通信是相通甚至就是相同的,因此在数学意义上自然语言处理和语言的初衷--通信联系在一起了;
统计语言模型--针对自然语言上下文相关这种特性
例如以下三句话:
- 我打算在17年每个星期写一些游戏相关的文章;
- 打算我在每个星期写一些文章游戏相关的17年;
- 打我在算每星期个一些文章写17年相关的游戏;
两种方式分析句子是否合理:
- 基于规则的角度来看:
- 第一个句子:合乎语法规则和语义规则;
- 第二个句子:不合乎语法规则,但是语义还在;
- 第三个句子:既不符合语法也没有语义;
当然这种方法已经证实是走不通的;
- 基于统计的角度来看:
贾里尼克用一个简单的统计模型很漂亮的解决了这个问题,一个句子是否合理,只需要看它的可能性的大小就行,而可能性可以用概率来衡量;
计算一个语句出现的概率:
S表示语句,该语句由w1,w2...wn等N个词组成;
P(S)表示语句S出现的概率;
既然不可能把上千年人们说过的话都统计出来,那么我们就需要一个用于估算的模型;
P(S)=P(w1,w2...wn)
利用条件概率公式:S这个序列出现的概率等于每个词出现的条件概率相乘,于是可以展开为:
P(w1,w2...wn)=P(w1)*P(w2|w1)*P(w3|w1,w2)...P(wn|w1,w2...wn-1)
其中P(w1)表示第一个词出现的概率,P(w2|w1)表示在第一个词出现的前提下,第二个词出现的概率,以此类推,可以看到,第n个词出现的概率取决于他前面的所有词;
从计算量上来讲,P(w1)很容易可以得到(在某一个语言字典中查找一个词的出现概率),P(w2|w1)也可以接受, 但是P(w3|w1,w2)就比较麻烦了,因为这需要计算三个不同的词的出现概率,而P(wn|w1,w2...wn-1)的计算量在n比较大时可能性就已经多到无法估算了,此时就需要使用马尔科夫假设;
马尔科夫假设:
每当遇到上述情况时,就假设任意一个词wi出现的概率只同它前面的最接近的一个单词相关,于是公式由:
P(w1)*P(w2|w1)*P(w3|w1,w2)...P(wn|w1,w2...wn-1)
变为:
P(w1)*P(w2|w1)*P(w3|w2)...P(wn|wn-1)
这种新的公式对应的统计语言模型是二元(每个词出现的概率需要考虑的词的个数)模型,接下来的问题就转为估算条件概率P(wi|wi-1),根据定义有:
P(wi|wi-1)=P(wi-1,wi)/P(wi-1)
P(wi-1,wi):即在某个语料库(Corpus)中,出现wi-1,wi并且是前后相邻关系的次数除以语料库的大小;
P(wi-1):即在同样的语料库中,出现单词wi-1的此处除以语料库的大小;
这些词或者二元组的相对频度(#表示语料库的大小):
f(wi-1,wi)=#(wi-1,wi)/#
f(wi-1)=#(wi-1)/#
而根据大数定理,只要统计量足够大,也就是语料库够大,那么相对频度就等于概率;
P(wi-1,wi)=f(wi-1,wi)
P(wi-1)=f(wi-1)
因此有:
P(wi|wi-1)=f(wi-1,wi)/f(wi-1)=#(wi-1,wi)/#(wi-1)
统计语言模型的工程诀窍
高阶语言模型
我们知道大部分情况下一个词都是与自身之前多个词有相关性的而不仅仅是最接近的那一个,因此更普遍的假设是假设某个词和前面n个词有关,这被称为n阶马尔科夫假设,对应的语言模型为n+1元模型,n为2就是上一小节的公式,当n为1时,表示与上下文无关,目前使用最多的是2阶马尔科夫假设,对应3元模型,这是因为从1元到2元到3元,效果的提升很大,而从3元到4元效果提升不大,但是对资源的消耗却急剧增加,当然,实际上不管是几阶的的模型都不可能覆盖所有语言现象,这是因为上下文之间的相关性可能跨度非常大,甚至是隔段落相关的,这个也是马尔科夫假设的局限性;
模型训练,零概率问题和平滑办法
当我们在进行训练时,例如二元模型,出现wi和wi-1都为0,或者都为1的情况时,由于出现的此处不够多,也就不满足于大数定理,那么就不能简单的得出0或者1这样的概率直接使用,那么我们该如何估算概率?
古德--图灵估计:
- 方式:在统计中相信可靠的统计数据,而对不可信的统计数据打折扣的一个概率估计方法,同时将折扣出来的那一小部分概率给予未看见的事件;
- 原理:对于没有看到的事件,我们不能直接认为它出现的概率为0,因此我们从概率的总量中,分配一个很小的比例给这些没有看见的事件,这样一来,看见的事件的总概率就小于1了,因此需要将所有看见的事件的概率下调一点,至于下调多少,根据"越是不可信的统计折扣越多"的方法;
- 实际:在实际处理中,会设置一个阈值,当出现次数小于这个阈值时,会下调概率给未出现的事件,而当大于这个阈值时则不会进行下调,这样出现次数多的词,它的概率估计就是它们的相对频度,而出现次数少的,概率就会略小于它的相对频度,而对于未看见的词也给予了一个比较小的概率,这样所有词的概率估计就都平滑了--卡兹退避法;
语料的选取问题
语料的选择取决了应用的领域,例如搜索引擎的语料选择则应该更多从网页中或者网络流量中获取,这样场景本身对应的话效果会更好;
分词
在一些亚洲语言,例如中文,日文,韩文和泰文中,每个字的意思是没有太大意义的,这个时候理解句子意思首先就需要做分词处理,同样可以通过统计模型来实现;
Thanks Doctor JunWu;