createMoMo

为了获得更大的灵活性,我们改变我们对待文法类别,如S,NP,V的方式,我们将这些原子标签分解为类似字典的结构,以便可以提取一系列的值作为特征。

9.1文法特征

先从一个简单的例子开始,使用字典存储特征和他们的值。

>>>kim = {\'CAT\':\'NP\', \'ORTH\': \'Kim\', \'REF\': \'k\'}
>>>chase = {\'CAT\':\'V\', \'ORTH\': \'chased\', \'REL\': \'chase\'}

CAT:文法类别;ORTH:拼写;REF:给出指示物或者关系。在基于规则的文法上下文中,这样的特征和特征值对被称为特征结构。

根据需要,我们还可以添加特征

>>>chase[\'AGT\'] = \'sbj\'
>>>chase[\'PAT\'] = \'obj\'

AGT :施事的角色,PAT:受事的角色,在这里是宾语。

例如,我们现在要处理句子:Kim chased Lee.

>>>sent = "Kim chased Lee"
>>>tokens = sent.split()
>>>lee = {\'CAT\':\'NP\', \'ORTH\': \'Lee\', \'REF\': \'l\'}
>>>def lex2fs(word):
    ... for fs in [kim, lee, chase]:
...         if fs[\'ORTH\'] ==word:
...             return fs
>>>subj, verb, obj = lex2fs(tokens[0]), lex2fs(tokens[1]), lex2fs(tokens[2])
>>>verb[\'AGT\'] = subj[\'REF\'] #agent of \'chase\' is Kim
>>>verb[\'PAT\'] =obj[\'REF\'] #patient of \'chase\' is Lee
>>>for kin [\'ORTH\', \'REL\', \'AGT\', \'PAT\']: #checkfeatstruct of\'chase\'
... print "%-5s =>%s"%(k, verb[k])
ORTH =>chased
REL =>chase
AGT =>k
PAT =>l

同样的方法可以适用不同的动词,可以添加更多的特征,例如:

>>>surprise = {\'CAT\':\'V\', \'ORTH\': \'surprised\', \'REL\': \'surprise\',
... \'SRC\': \'sbj\', \'EXP\': \'obj\'}

句法协议

动词的形态属性与主语名词短语的属性一起变化,这种变化被成为协议(agreement)。

例如:

a. the dog runs
b.*the dog run
a. the dogs run
b.*the dogs runs

我们可以使用改进文法的方式,来处理这种情况,下面是一个例子,但是需要注意,这种方法是非常麻烦的。

改进之前的文法:

(7) S -> NPVP
NP -> DetN
VP -> V
Det -> \'this\'
N -> \'dog\'
V -> \'runs\'

改进之后的文法:

(8) S -> NP_SGVP_SG
S -> NP_PLVP_PL
NP_SG-> Det_SGN_SG
NP_PL-> Det_PLN_PL
VP_SG-> V_SG
VP_PL-> V_PL
Det_SG-> \'this\'
Det_PL-> \'these\'
N_SG-> \'dog\'
N_PL-> \'dogs\'
V_SG-> \'runs\'
V_PL-> \'run\'

为了避免这种爆炸式的增加,我们可以使用属性和约束。

使用属性和约束

Det[NUM=sg]-> \'this\'
Det[NUM=pl]-> \'these\'
N[NUM=sg]-> \'dog\'
N[NUM=pl]-> \'dogs\'
V[NUM=sg]-> \'runs\'
V[NUM=pl]-> \'run\'

我们可以使用?n来改进:

S -> NP[NUM=?n]VP[NUM=?n]
NP[NUM=?n]-> Det[NUM=?n]N[NUM=?n]
VP[NUM=?n]-> V[NUM=?n]

但是有些词是对单复数没有挑剔的,有两种表示方法,很显然,第二种,是比第一种要简单明了的。

第一种:

Det[NUM=sg]-> \'the\' | \'some\' | \'several\'
Det[NUM=pl]-> \'the\' | \'some\' | \'several\'

第二种:

Det[NUM=?n]-> \'the\' | \'some\' | \'several\'

下面的代码演示了到目前为止在本章中介绍过的大多数想法:

>>>nltk.data.show_cfg(\'grammars/book_grammars/feat0.fcfg\')
%start S
####################
#GrammarProductions
####################
#S expansion productions
S -> NP[NUM=?n]VP[NUM=?n]
#NPexpansion productions
NP[NUM=?n]-> N[NUM=?n]
NP[NUM=?n]-> PropN[NUM=?n]
NP[NUM=?n]-> Det[NUM=?n]N[NUM=?n]
NP[NUM=pl]-> N[NUM=pl]
#VPexpansion productions
VP[TENSE=?t,NUM=?n]-> IV[TENSE=?t, NUM=?n]
VP[TENSE=?t,NUM=?n]-> TV[TENSE=?t,NUM=?n]NP
####################
#LexicalProductions
####################
Det[NUM=sg]-> \'this\' | \'every\'
Det[NUM=pl]-> \'these\' | \'all\'
Det-> \'the\' | \'some\' | \'several\'
PropN[NUM=sg]->\'Kim\' | \'Jody\'
N[NUM=sg]-> \'dog\' | \'girl\' | \'car\' | \'child\'
N[NUM=pl]-> \'dogs\' | \'girls\' | \'cars\' | \'children\'
IV[TENSE=pres, NUM=sg]-> \'disappears\' | \'walks\'
TV[TENSE=pres,NUM=sg]-> \'sees\' | \'likes\'
IV[TENSE=pres, NUM=pl]-> \'disappear\' | \'walk\'
TV[TENSE=pres,NUM=pl]-> \'see\' | \'like\'
IV[TENSE=past] -> \'disappeared\' | \'walked\'
TV[TENSE=past]-> \'saw\' | \'liked\'

下面的代码展示了,如何解析一句话:

如果文法无法分析输入,trees将为空,否则会包含一个或多个分析树。取决于舒服是否有句法歧义。

>>>tokens = \'Kim likes children\'.split()
>>>from nltk import load_parser �
>>>cp = load_parser(\'grammars/book_grammars/feat0.fcfg\', trace=2) �
>>>trees = cp.nbest_parse(tokens)
|.Kim .like.chil.|
|[----] . .| PropN[NUM=\'sg\']-> \'Kim\' *
|[----] . .| NP[NUM=\'sg\']-> PropN[NUM=\'sg\']*
|[----> . .| S[]-> NP[NUM=?n]*VP[NUM=?n]{?n: \'sg\'}
|. [----] .| TV[NUM=\'sg\',TENSE=\'pres\']-> \'likes\' *
|. [----> .| VP[NUM=?n,TENSE=?t]-> TV[NUM=?n,TENSE=?t]*NP[]
{?n: \'sg\', ?t: \'pres\'}
|. . [----]| N[NUM=\'pl\']-> \'children\' *
|. . [----]| NP[NUM=\'pl\']-> N[NUM=\'pl\']*
|. . [---->| S[]-> NP[NUM=?n]*VP[NUM=?n]{?n: \'pl\'}
|. [---------]| VP[NUM=\'sg\',TENSE=\'pres\']
-> TV[NUM=\'sg\',TENSE=\'pres\']NP[]*
|[==============]| S[]-> NP[NUM=\'sg\']VP[NUM=\'sg\']*

最后,可以检查分析树:

>>>for tree in trees: print tree
(S[]
(NP[NUM=\'sg\'] (PropN[NUM=\'sg\'] Kim))
(VP[NUM=\'sg\', TENSE=\'pres\']
(TV[NUM=\'sg\', TENSE=\'pres\']likes)
(NP[NUM=\'pl\'] (N[NUM=\'pl\'] children))))

术语

像sg,pl这样的简单的值通常被成为原子。原子值的一种特殊情况是布尔值,仅仅指定一个属性是真还是假。

例如AUX代表助动词。

V[TENSE=pres,aux=+]->\'can\'

有的时候,我们可以将协议特征组合在一起,作为一个类别的不同部分,表示AGR的值。

属性值矩阵:AVM

[POS = N ]
[                  ]
[AGR = [PER = 3 ]]
[ [NUM = pl ]]
[ [GND = fem ]]

当有复杂的属性时,可以重构文法:

S -> NP[AGR=?n]VP[AGR=?n]
NP[AGR=?n]-> PropN[AGR=?n]
VP[TENSE=?t,AGR=?n]-> Cop[TENSE=?t,AGR=?n]Adj
Cop[TENSE=pres, AGR=[NUM=sg,PER=3]]-> \'is\'
PropN[AGR=[NUM=sg,PER=3]]-> \'Kim\'
Adj-> \'happy\'

分类:

技术点:

相关文章:

  • 2021-07-23
  • 2021-09-02
  • 2021-10-02
  • 2021-07-03
  • 2021-07-27
  • 2022-12-23
  • 2021-08-13
猜你喜欢
  • 2022-12-23
  • 2021-05-06
  • 2021-08-29
  • 2021-12-03
  • 2021-10-19
  • 2022-12-23
相关资源
相似解决方案