短语结构文法是关于词和词序列如何结合起来形成句子成分的。
依存文法是一个独特的和互补的方式,集中关注的是词与其他词之间的关系。依存关系是一个中心词与它的依赖之间的二元对称关系。一个句子的中心通常是动词,所有其他词要么依赖于中心词,要么依赖路径与它联通。
依赖关系表示是一个加标签的有向图,其中节点是词汇项,加标签的弧表示依赖关系,从中心词到依赖。
图中显示了一个依存关系图,箭头从中心词指向它们的依赖。
1、shot是整个句子的中心词;
2、I是shot的SBJ(主语)
3、in是一个NMOD(elephant的名词修饰词)
4、与短语结构文法相比,依存文法可以作为一种依存关系直接用来表示语法功能。
下面是NLTK为依存文法编码的一种方式-注意他只能捕捉依存关系信息,不能指定依存关系类型:
>>>groucho_dep_grammar= nltk.parse_dependency_grammar(""" ... 'shot' -> 'I' | 'elephant' | 'in' ... 'elephant' -> 'an' | 'in' ... 'in' -> 'pajamas' ... 'pajamas' -> 'my' ... """) >>>print groucho_dep_grammar Dependency grammar with 7 productions 'shot' -> 'I' 'shot' -> 'elephant' 'shot' -> 'in' 'elephant' -> 'an' 'elephant' -> 'in' 'in' -> 'pajamas' 'pajamas' -> 'my'
下面的例子,演示了如何捕捉歧义:
>>>pdp= nltk.ProjectiveDependencyParser(groucho_dep_grammar) >>>sent = 'I shot an elephant in mypajamas'.split() >>>trees = pdp.parse(sent) >>>for tree in trees: ... print tree (shot I (elephant an (in (pajamas my)))) (shot I (elephant an) (in (pajamas my)))
配价与词汇
我们来看这样一组句子:
(12)a. Thesquirrel wasfrightened.
b.Chatterersaw the bear.
c.Chattererthought Busterwasangry.
d.Joe put the fish onthe log.
这些句子对应着下面这个表格,展示了VP产生式和他们的中心词汇
在表中,动词被认为具有不同的配价。
依赖ADJ,NP,PP和S通常背成为各自动词的补语。
为了扩展VP后动词至于他们正确的补语一同出现,我们可以通过将动词划分成更多的子类别做到这个,每个子类别与一组不同的补语关联。例如:及物动词后面需要跟NP;可以为及物动词引入一个新的标签,叫做TV。
VP-> TV NP TV-> 'chased' | 'saw'
扩大规模
如果把这种做法可以扩大到覆盖自然语言的大型语料库,手工构建这样一套产生式是非常困难的。
8.6文法开发
在这一节中尝试扩大这种方法的规模来处理现实的语言语料库。这这里访问树库,并看看开发广泛覆盖的文法的挑战。
树库和文法
corpus模块定义了树库语料的阅读器。
>>>from nltk.corpusimport treebank >>>t =treebank.parsed_sents('wsj_0001.mrg')[0] >>>print t (S (NP-SBJ (NP (NNP Pierre)(NNP Vinken)) (, ,) (ADJP (NP (CD 61)(NNS years))(JJ old)) (, ,)) (VP (MD will) (VP (VB join) (NP (DT the) (NN board)) (PP-CLR (IN as) (NP (DT a) (JJ nonexecutive) (NN director))) (NP-TMP (NNP Nov.)(CD 29)))) (. .))
在下面的程序中,使用了一个简单的过滤器找出带句子补语的动词。
假设我们已经有了一个形如VP->SV S的产生式,这个信息使我们能够识别出那些包括在SV中的扩张中的特别的动词。
#搜索树库找出句子的补语 def filter(tree): child_nodes = [child.node for child in tree if isinstance(child, nltk.Tree)] return (tree.node =='VP') and ('S' in child_nodes) >>>from nltk.corpusimport treebank >>>[subtree for tree in treebank.parsed_sents() ... for subtree in tree.subtrees(filter)] [Tree('VP', [Tree('VBN', ['named']), Tree('S',[Tree('NP-SBJ', ...]), ...]), ...]
nltk.corpus.ppattach是一个关于特别动词配价的信息源。在这里找出具有固定介词和名词的介词短语对,其中介词短语附着到VP还是NP,由选择的动词决定。
>>>entries = nltk.corpus.ppattach.attachments('training') >>>table = nltk.defaultdict(lambda: nltk.defaultdict(set)) >>>for entry in entries: ... key = entry.noun1 + '-' +entry.prep + '-' + entry.noun2 ... table[key][entry.attachment].add(entry.verb) ... >>>for keyin sorted(table): .. . if len(table[key]) > 1: ... print key,'N:', sorted(table[key]['N']), 'V:', sorted(table[key]['V'])
有害的歧义
文法分析是容易产生歧义的.在这里不做过多的解释,有的时候在分析句子的时候可怕的低效.
为了解决这个问题,概率分析会帮我们解决,它使我们能够以来自语料库的证据为基础对歧义句的解析进行排名.
加权文法
概率上下文无关文法(probabilistic context-free grammar,PCFG)是一种上下文无关文法,他的每一个产生式关联一个概率。PCFG产生的一个解析的概率,仅仅是他用到的产生式的概率的乘积。
如下面这个文法:
grammar= nltk.parse_pcfg(""" S -> NPVP [1.0] VP -> TVNP [0.4] VP -> IV [0.3] VP -> DatVNPNP [0.3] TV -> 'saw' [1.0] IV -> 'ate' [1.0] DatV-> 'gave' [1.0] NP -> 'telescopes' [0.8] NP -> 'Jack' [0.2] """)
为了确保由文法生成的树能形成概率分布,PCFG文法强加了约束:产生式所有给定的左侧的概率之和必须为1。
>>>viterbi_parser= nltk.ViterbiParser(grammar) >>>print viterbi_parser.parse(['Jack','saw', 'telescopes']) (S (NP Jack) (VP (TV saw) (NP telescopes))) (p=0.064)