【语言处理与Python】8.5依存关系和依存文法\8.6文法开发

时间:2022-03-13 07:37:57

短语结构文法是关于词和词序列如何结合起来形成句子成分的。

依存文法是一个独特的和互补的方式,集中关注的是词与其他词之间的关系。依存关系是一个中心词与它的依赖之间的二元对称关系。一个句子的中心通常是动词,所有其他词要么依赖于中心词,要么依赖路径与它联通。

依赖关系表示是一个加标签的有向图,其中节点是词汇项,加标签的弧表示依赖关系,从中心词到依赖。

图中显示了一个依存关系图,箭头从中心词指向它们的依赖。

【语言处理与Python】8.5依存关系和依存文法\8.6文法开发

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产生式和他们的中心词汇

【语言处理与Python】8.5依存关系和依存文法\8.6文法开发

在表中,动词被认为具有不同的配价。

依赖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)是一种上下文无关文法,他的每一个产生式关联一个概率。PCF*生的一个解析的概率,仅仅是他用到的产生式的概率的乘积。

如下面这个文法:

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)