七-文法分析

语法分析固然重要,但要想覆盖语言的全部,需要进一步扩展到文法分析,文法分析可以基于规则,但是工作量难以想象,基于特征的文法分析不但可穷举,而且可以方便用计算机存储和计算,本节简单做一个介绍,更深层次的内容还需要继续关注后面的系列文章

语法和文法

还记得上一节中的这个吗?

1
2
3
4
5
6
7
(S
    (NP 小明) 
    (VP
        (V 追赶) 
        (NP
            (Det 一只) 
            (N 兔子)))) 

这里面的N表示名词,Det表示限定词,NP表示名词短语,V表示动词,VP表示动词短语,S表示句子

这种句子分析方法叫做语法分析

因为句子可以无限组合无限扩展,所以单纯用语法分析来完成自然语言处理这件事情是不可能的,所以出现了文法分析

文法是一个潜在的无限的句子集合的一个紧凑的特性,它是通过一组形式化模型来表示的,文法可以覆盖所有结构的句子,对一个句子做文法分析,就是把句子往文法模型上靠,如果同时符合多种文法,那就是有歧义的句子

最重要的结论:文法结构范围相当广泛,无法用规则类的方法来处理,只有利用基于特征的方法才能处理

文法特征结构

文法特征举例:单词最后一个字母、词性标签、文法类别、正字拼写、指示物、关系、施事角色、受事角色

因为文法特征是一种kv,所以特征结构的存储形式是字典

不是什么样的句子都能提取出每一个文法特征的,需要满足一定的条件,这需要通过一系列的检查手段来达到,包括:句法协议(比如this dog就是对的,而these dog就是错的)、属性和约束、术语

特征结构的处理

nltk帮我实现了特征结构:

1
2
3
4
5
6
7
>>> import nltk
>>> fs1 = nltk.FeatStruct(TENSE='past', NUM='sg')
>>> fs1
[NUM='sg', TENSE='past']
>>> fs2 = nltk.FeatStruct(POS='N', AGR=fs1)
>>> fs2
[AGR=[NUM='sg', TENSE='past'], POS='N']

在nltk的库里已经有了一些产生式文法描述可以直接使用,位置在:

1
2
[root@centos $] ls ~/nltk_data/grammars/book_grammars
background.fol  discourse.fcfg  drt.fcfg  feat0.fcfg  feat1.fcfg  german.fcfg  simple-sem.fcfg  sql0.fcfg  sql1.fcfg  storage.fcfg

我们看其中最简单的一个sql0.fcfg,这是一个查找国家城市的sql语句的文法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
% start S

S[SEM=(?np + WHERE + ?vp)] -> NP[SEM=?np] VP[SEM=?vp]

VP[SEM=(?v + ?pp)] -> IV[SEM=?v] PP[SEM=?pp]
VP[SEM=(?v + ?ap)] -> IV[SEM=?v] AP[SEM=?ap]
NP[SEM=(?det + ?n)] -> Det[SEM=?det] N[SEM=?n]
PP[SEM=(?p + ?np)] -> P[SEM=?p] NP[SEM=?np]
AP[SEM=?pp] -> A[SEM=?a] PP[SEM=?pp]

NP[SEM='Country="greece"'] -> 'Greece'
NP[SEM='Country="china"'] -> 'China'

Det[SEM='SELECT'] -> 'Which' | 'What'

N[SEM='City FROM city_table'] -> 'cities'

IV[SEM=''] -> 'are'
A[SEM=''] -> 'located'
P[SEM=''] -> 'in'

解释一下

这里面从上到下是从最大范围到最小范围一个个的解释,S是句子

我们来加载这个文法描述,并试验如下:

1
2
3
4
5
6
7
import nltk
from nltk import load_parser
cp = load_parser('grammars/book_grammars/sql0.fcfg')
query = 'What cities are located in China'
tokens = query.split()
for tree in cp.parse(tokens):
    print tree

输出结果如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
(S[SEM=(SELECT, City FROM city_table, WHERE, , , Country="china")]
  (NP[SEM=(SELECT, City FROM city_table)]
    (Det[SEM='SELECT'] What)
    (N[SEM='City FROM city_table'] cities))
  (VP[SEM=(, , Country="china")]
    (IV[SEM=''] are)
    (AP[SEM=(, Country="china")]
      (A[SEM=''] located)
      (PP[SEM=(, Country="china")]
        (P[SEM=''] in)
        (NP[SEM='Country="china"'] China)))))

我们可以看到用特征结构可以建立对大量广泛的语言学现象的简介分析