2 处理特征结构

在本节中,我们将展示如何在 NLTK 中构建和操作特征结构。我们还将讨论统一的基本操作,这使我们能够结合两个不同的特征结构中的信息。

NLTK 中的特征结构使用构造函数FeatStruct()声明。原子特征值可以是字符串或整数。

  1. >>> fs1 = nltk.FeatStruct(TENSE='past', NUM='sg')
  2. >>> print(fs1)
  3. [ NUM = 'sg' ]
  4. [ TENSE = 'past' ]

一个特征结构实际上只是一种字典,所以我们可以平常的方式通过索引访问它的值。我们可以用我们熟悉的方式 值给特征:

  1. >>> fs1 = nltk.FeatStruct(PER=3, NUM='pl', GND='fem')
  2. >>> print(fs1['GND'])
  3. fem
  4. >>> fs1['CASE'] = 'acc'

我们还可以为特征结构定义更复杂的值,如前面所讨论的。

  1. >>> fs2 = nltk.FeatStruct(POS='N', AGR=fs1)
  2. >>> print(fs2)
  3. [ [ CASE = 'acc' ] ]
  4. [ AGR = [ GND = 'fem' ] ]
  5. [ [ NUM = 'pl' ] ]
  6. [ [ PER = 3 ] ]
  7. [ ]
  8. [ POS = 'N' ]
  9. >>> print(fs2['AGR'])
  10. [ CASE = 'acc' ]
  11. [ GND = 'fem' ]
  12. [ NUM = 'pl' ]
  13. [ PER = 3 ]
  14. >>> print(fs2['AGR']['PER'])
  15. 3

指定特征结构的另一种方法是使用包含feature=value格式的特征-值对的方括号括起的字符串,其中值本身可能是特征结构:

  1. >>> print(nltk.FeatStruct("[POS='N', AGR=[PER=3, NUM='pl', GND='fem']]"))
  2. [ [ GND = 'fem' ] ]
  3. [ AGR = [ NUM = 'pl' ] ]
  4. [ [ PER = 3 ] ]
  5. [ ]
  6. [ POS = 'N' ]

特征结构本身并不依赖于语言对象;它们是表示知识的通用目的的结构。例如,我们可以将一个人的信息用特征结构编码:

  1. >>> print(nltk.FeatStruct(NAME='Lee', TELNO='01 27 86 42 96', AGE=33))
  2. [ AGE = 33 ]
  3. [ NAME = 'Lee' ]
  4. [ TELNO = '01 27 86 42 96' ]

在接下来的几页中,我们会使用这样的例子来探讨特征结构的标准操作。这将使我们暂时从自然语言处理转移,因为在我们回来谈论语法之前需要打下基础。坚持!

将特征结构作为图来查看往往是有用的;更具体的,作为有向无环图(DAG)。(19)等同于上面的 AVM。

  1. >>> print(nltk.FeatStruct("""[NAME='Lee', ADDRESS=(1)[NUMBER=74, STREET='rue Pascal'],
  2. ... SPOUSE=[NAME='Kim', ADDRESS->(1)]]"""))
  3. [ ADDRESS = (1) [ NUMBER = 74 ] ]
  4. [ [ STREET = 'rue Pascal' ] ]
  5. [ ]
  6. [ NAME = 'Lee' ]
  7. [ ]
  8. [ SPOUSE = [ ADDRESS -> (1) ] ]
  9. [ [ NAME = 'Kim' ] ]

括号内的整数有时也被称为标记或同指标志。整数的选择并不重要。可以有任意数目的标记在一个单独的特征结构中。

  1. >>> print(nltk.FeatStruct("[A='a', B=(1)[C='c'], D->(1), E->(1)]"))
  2. [ A = 'a' ]
  3. [ ]
  4. [ B = (1) [ C = 'c' ] ]
  5. [ ]
  6. [ D -> (1) ]
  7. [ E -> (1) ]