第09章 建立基于特征的文法

  • 9.1 文法特征
    • 句法协议
    • 使用属性和约束
    • 术语
  • 9.2 处理特征结构
    • 包含和统一
  • 9.3 扩展基于特征的文法
    • 子类别
    • 核心词回顾
    • 助动词与倒装
    • 无限制依赖成分
  • 9.4 小结
import nltk
  1. 怎样用特征扩展上下文无关文法框架,以获得更细粒度的对文法类别和产生式的控制?
  2. 特征结构的主要形式化属性是什么,如何使用它们来计算?
  3. 用基于特征的文法能捕捉到什么语言模式和文法结构?

9.1 文法特征

基于规则的文法上下文中,特征和特征值对被称为特征结构

kim = {'CAT': 'NP', 'ORTH': 'Kim', 'REF': 'k'}
chase = {'CAT': 'V', 'ORTH': 'chased', 'REL': 'chase'}
chase['AGT'] = 'sbj'
chase['PAT'] = 'obj'

一个简单的假设:在动词直接左侧和右侧的NP 分别是主语和宾语。

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 k in ['ORTH', 'REL', 'AGT', 'PAT']: # check featstruct 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)。

表9-1. 英语规则动词的协议范式

单数 复数
第一人称 I run we run
第二人称 you run you run
第三人称 he/she/it runs they run

使用属性和约束

例9-1. 基于特征的文法的例子。

nltk.data.show_cfg('grammars/book_grammars/feat0.fcfg')
% start S
# ###################
# Grammar Productions
# ###################
# S expansion productions
S -> NP[NUM=?n] VP[NUM=?n]
# NP expansion 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]
# VP expansion productions
VP[TENSE=?t, NUM=?n] -> IV[TENSE=?t, NUM=?n]
VP[TENSE=?t, NUM=?n] -> TV[TENSE=?t, NUM=?n] NP
# ###################
# Lexical Productions
# ###################
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'

例9-2. 跟踪基于特征的图表分析器

tokens = 'Kim likes children'.split()
from nltk import load_parser
cp = load_parser('grammars/book_grammars/feat0.fcfg', trace=2)
for tree in cp.parse(tokens):print(tree)
|.Kim .like.chil.|
Leaf Init Rule:
|[----]    .    .| [0:1] 'Kim'
|.    [----]    .| [1:2] 'likes'
|.    .    [----]| [2:3] 'children'
Feature Bottom Up Predict Combine Rule:
|[----]    .    .| [0:1] PropN[NUM='sg'] -> 'Kim' *
Feature Bottom Up Predict Combine Rule:
|[----]    .    .| [0:1] NP[NUM='sg'] -> PropN[NUM='sg'] *
Feature Bottom Up Predict Combine Rule:
|[---->    .    .| [0:1] S[] -> NP[NUM=?n] * VP[NUM=?n] {?n: 'sg'}
Feature Bottom Up Predict Combine Rule:
|.    [----]    .| [1:2] TV[NUM='sg', TENSE='pres'] -> 'likes' *
Feature Bottom Up Predict Combine Rule:
|.    [---->    .| [1:2] VP[NUM=?n, TENSE=?t] -> TV[NUM=?n, TENSE=?t] * NP[] {?n: 'sg', ?t: 'pres'}
Feature Bottom Up Predict Combine Rule:
|.    .    [----]| [2:3] N[NUM='pl'] -> 'children' *
Feature Bottom Up Predict Combine Rule:
|.    .    [----]| [2:3] NP[NUM='pl'] -> N[NUM='pl'] *
Feature Bottom Up Predict Combine Rule:
|.    .    [---->| [2:3] S[] -> NP[NUM=?n] * VP[NUM=?n] {?n: 'pl'}
Feature Single Edge Fundamental Rule:
|.    [---------]| [1:3] VP[NUM='sg', TENSE='pres'] -> TV[NUM='sg', TENSE='pres'] NP[] *
Feature Single Edge Fundamental Rule:
|[==============]| [0:3] S[] -> NP[NUM='sg'] VP[NUM='sg'] *
(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))))

术语

9.2 处理特征结构

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

fs1 = nltk.FeatStruct(TENSE='past', NUM='sg')
print(fs1)
[ NUM   = 'sg'   ]
[ TENSE = 'past' ]
fs1 = nltk.FeatStruct(PER=3, NUM='pl', GND='fem')
print(fs1['GND'])
fem
fs1['CASE'] = 'acc'
fs2 = nltk.FeatStruct(POS='N', AGR=fs1)
print(fs2)
[       [ CASE = 'acc' ] ]
[ AGR = [ GND  = 'fem' ] ]
[       [ NUM  = 'pl'  ] ]
[       [ PER  = 3     ] ]
[                        ]
[ POS = 'N'              ]
print(fs2['AGR'])
[ CASE = 'acc' ]
[ GND  = 'fem' ]
[ NUM  = 'pl'  ]
[ PER  = 3     ]
print(fs2['AGR']['PER'])
3
print(nltk.FeatStruct("[POS='N', AGR=[PER=3, NUM='pl', GND='fem']]"))
[       [ GND = 'fem' ] ]
[ AGR = [ NUM = 'pl'  ] ]
[       [ PER = 3     ] ]
[                       ]
[ POS = 'N'             ]
print(nltk.FeatStruct(NAME='Lee', TELNO='01 27 86 42 96', AGE=33))
[ AGE   = 33               ]
[ NAME  = 'Lee'            ]
[ TELNO = '01 27 86 42 96' ]
print(nltk.FeatStruct("""[NAME='Lee', ADDRESS=(1)[NUMBER=74, STREET='rue Pascal'],SPOUSE=[NAME='Kim', ADDRESS->(1)]]"""))
[ ADDRESS = (1) [ NUMBER = 74           ] ]
[               [ STREET = 'rue Pascal' ] ]
[                                         ]
[ NAME    = 'Lee'                         ]
[                                         ]
[ SPOUSE  = [ ADDRESS -> (1)  ]           ]
[           [ NAME    = 'Kim' ]           ]
print(nltk.FeatStruct("[A='a', B=(1)[C='c'], D->(1), E->(1)]"))
[ A = 'a'             ]
[                     ]
[ B = (1) [ C = 'c' ] ]
[                     ]
[ D -> (1)            ]
[ E -> (1)            ]

包含和统一

fs1 = nltk.FeatStruct(NUMBER=74, STREET='rue Pascal')
fs2 = nltk.FeatStruct(CITY='Paris')
print(fs2.unify(fs1))
[ CITY   = 'Paris'      ]
[ NUMBER = 74           ]
[ STREET = 'rue Pascal' ]
fs0 = nltk.FeatStruct(A='a')
fs1 = nltk.FeatStruct(A='b')
fs2 = fs0.unify(fs1)
print(fs2)
None
fs0 = nltk.FeatStruct("""[NAME=Lee,ADDRESS=[NUMBER=74,STREET='rue Pascal'],SPOUSE= [NAME=Kim,ADDRESS=[NUMBER=74,STREET='rue Pascal']]]""")
print(fs0)
[ ADDRESS = [ NUMBER = 74           ]               ]
[           [ STREET = 'rue Pascal' ]               ]
[                                                   ]
[ NAME    = 'Lee'                                   ]
[                                                   ]
[           [ ADDRESS = [ NUMBER = 74           ] ] ]
[ SPOUSE  = [           [ STREET = 'rue Pascal' ] ] ]
[           [                                     ] ]
[           [ NAME    = 'Kim'                     ] ]
fs1 = nltk.FeatStruct("[SPOUSE = [ADDRESS = [CITY = Paris]]]")
print(fs1.unify(fs0))
[ ADDRESS = [ NUMBER = 74           ]               ]
[           [ STREET = 'rue Pascal' ]               ]
[                                                   ]
[ NAME    = 'Lee'                                   ]
[                                                   ]
[           [           [ CITY   = 'Paris'      ] ] ]
[           [ ADDRESS = [ NUMBER = 74           ] ] ]
[ SPOUSE  = [           [ STREET = 'rue Pascal' ] ] ]
[           [                                     ] ]
[           [ NAME    = 'Kim'                     ] ]
fs2 = nltk.FeatStruct("""[NAME=Lee, ADDRESS=(1)[NUMBER=74, STREET='rue Pascal'],
SPOUSE=[NAME=Kim, ADDRESS->(1)]]""")
print(fs1.unify(fs2))
[               [ CITY   = 'Paris'      ] ]
[ ADDRESS = (1) [ NUMBER = 74           ] ]
[               [ STREET = 'rue Pascal' ] ]
[                                         ]
[ NAME    = 'Lee'                         ]
[                                         ]
[ SPOUSE  = [ ADDRESS -> (1)  ]           ]
[           [ NAME    = 'Kim' ]           ]
fs1 = nltk.FeatStruct("[ADDRESS1=[NUMBER=74, STREET='rue Pascal']]")
fs2 = nltk.FeatStruct("[ADDRESS1=?x, ADDRESS2=?x]")
print(fs2)
[ ADDRESS1 = ?x ]
[ ADDRESS2 = ?x ]
print(fs2.unify(fs1))
[ ADDRESS1 = (1) [ NUMBER = 74           ] ]
[                [ STREET = 'rue Pascal' ] ]
[                                          ]
[ ADDRESS2 -> (1)                          ]

9.3 扩展基于特征的文法

子类别

核心词回顾

助动词与倒装

无限制依赖成分

例9-3. 具有倒装从句和长距离依赖的产生式的文法,使用斜线类别。

nltk.data.show_cfg('grammars/book_grammars/feat1.fcfg')
% start S
# ###################
# Grammar Productions
# ###################
S[-INV] -> NP VP
S[-INV]/?x -> NP VP/?x
S[-INV] -> NP S/NP
S[-INV] -> Adv[+NEG] S[+INV]
S[+INV] -> V[+AUX] NP VP
S[+INV]/?x -> V[+AUX] NP VP/?x
SBar -> Comp S[-INV]
SBar/?x -> Comp S[-INV]/?x
VP -> V[SUBCAT=intrans, -AUX]
VP -> V[SUBCAT=trans, -AUX] NP
VP/?x -> V[SUBCAT=trans, -AUX] NP/?x
VP -> V[SUBCAT=clause, -AUX] SBar
VP/?x -> V[SUBCAT=clause, -AUX] SBar/?x
VP -> V[+AUX] VP
VP/?x -> V[+AUX] VP/?x
# ###################
# Lexical Productions
# ###################
V[SUBCAT=intrans, -AUX] -> 'walk' | 'sing'
V[SUBCAT=trans, -AUX] -> 'see' | 'like'
V[SUBCAT=clause, -AUX] -> 'say' | 'claim'
V[+AUX] -> 'do' | 'can'
NP[-WH] -> 'you' | 'cats'
NP[+WH] -> 'who'
Adv[+NEG] -> 'rarely' | 'never'
NP/NP ->
Comp -> 'that'
tokens = 'who do you claim that you like'.split()
from nltk import load_parser
cp = load_parser('grammars/book_grammars/feat1.fcfg')
for tree in cp.parse(tokens):print(tree)
(S[-INV](NP[+WH] who)(S[+INV]/NP[](V[+AUX] do)(NP[-WH] you)(VP[]/NP[](V[-AUX, SUBCAT='clause'] claim)(SBar[]/NP[](Comp[] that)(S[-INV]/NP[](NP[-WH] you)(VP[]/NP[] (V[-AUX, SUBCAT='trans'] like) (NP[]/NP[] )))))))
tokens = 'you claim that you like cats'.split()
for tree in cp.parse(tokens):print(tree)
(S[-INV](NP[-WH] you)(VP[](V[-AUX, SUBCAT='clause'] claim)(SBar[](Comp[] that)(S[-INV](NP[-WH] you)(VP[] (V[-AUX, SUBCAT='trans'] like) (NP[-WH] cats))))))
tokens = 'rarely do you sing'.split()
for tree in cp.parse(tokens):print(tree)
(S[-INV](Adv[+NEG] rarely)(S[+INV](V[+AUX] do)(NP[-WH] you)(VP[] (V[-AUX, SUBCAT='intrans'] sing))))

9.4 小结

  • 上下文无关文法的传统分类是原子符号。特征结构的一个重要的作用是捕捉精细的区分,否则将需要数量翻倍的原子类别。
  • 通过使用特征值上的变量,我们可以表达文法产生式中的限制,允许不同的特征规格的实现可以相互依赖。
  • 通常情况下,我们在词汇层面指定固定的特征值,限制短语中的特征值与它们的原子中的对应值统一。
  • 特征值可以是原子的或复杂的。原子值的一个特定类别是布尔值,按照惯例用[+/- feat]表示。
  • 两个特征可以共享一个值(原子的或复杂的)。具有共享值的结构被称为重入。共享的值被表示为AVM 中的数字索引(或标记)。
  • 一个特征结构中的路径是一个特征的元组,对应从图的根开始的弧的序列上的标签。
  • 两条路径是等价的,如果它们共享一个值。
  • 包含的特征结构是偏序的。FS0 包含FS1,当FS0 比FS1 更一般(较少信息)。
  • 两种结构FS0 和FS1 的统一,如果成功,就是包含FS0 和FS1 的合并信息的特征结构FS2。
  • 如果统一在FS 中指定一条路径π,那么它也指定等效与π的每个路径π’。
  • 我们可以使用特征结构建立对大量广泛语言学现象的简洁的分析,包括动词子类别,倒装结构,无限制依赖结构和格支配。

致谢
《Python自然语言处理》123 4,作者:Steven Bird, Ewan Klein & Edward Loper,是实践性很强的一部入门读物,2009年第一版,2015年第二版,本学习笔记结合上述版本,对部分内容进行了延伸学习、练习,在此分享,期待对大家有所帮助,欢迎加我微信(验证:NLP),一起学习讨论,不足之处,欢迎指正。

参考文献


  1. http://nltk.org/ ↩︎

  2. Steven Bird, Ewan Klein & Edward Loper,Natural Language Processing with Python,2009 ↩︎

  3. (英)伯德,(英)克莱因,(美)洛普,《Python自然语言处理》,2010年,东南大学出版社 ↩︎

  4. Steven Bird, Ewan Klein & Edward Loper,Natural Language Processing with Python,2015 ↩︎

《Python自然语言处理(第二版)-Steven Bird等》学习笔记:第09章 建立基于特征的文法相关推荐

  1. 《用Python进行自然语言处理》第 9 章 建立基于特征的文法

    1. 我们怎样用特征扩展上下文无关文法框架,以获得更细粒度的对文法类别和产生式的控制? 2. 特征结构的主要形式化属性是什么,我们如何使用它们来计算? 3. 我们现在用基于特征的文法能捕捉到什么语言模 ...

  2. 【Python 自然语言处理 第二版】读书笔记1:语言处理与Python

    文章目录 前言 语言处理与Python 一.语言计算:文本和单词 1.NLTK入门 (1)安装(nltk.nltk.book) (2)搜索文本 (3)词汇计数 2.列表与字符串 (1)列表操作 (2) ...

  3. 学完可以解决90%以上的数据分析问题-利用python进行数据分析第二版(代码和中文笔记)...

    <利用python进行数据分析>是数据分析的基础教程,绝大部分数据分析师的入门教材,目前已经升级到第二版.本站搜集了教材的第二版原版代码进行中文翻译和注释,并做了一定的笔记.基本上只需要看 ...

  4. 【Python 自然语言处理 第二版】读书笔记2:获得文本语料和词汇资源

    文章目录 一.获取文本语料库 1.古腾堡语料库 (1)输出语料库中的文件标识符 (2)词的统计与索引 (3)文本统计 2.网络和聊天文本 3.布朗语料库 (1)初识 (2)比较不同文体中的情态动词的用 ...

  5. 鸟哥Linux私房菜_基础篇(第二版)_第十章学习笔记

    第十章 vi文字处理器 编辑器 vi 1.一般模式 2.编辑模式 3.命令行模式 注意:在vi编辑模式中 Tab键与空格键的不同 向上(k)   向下(j)  向左(h)  向右(l) ctrl+f ...

  6. 《Python编程:从入门到实践》学习笔记——第11章 测试代码

    文章目录 前言 1 测试函数 1.1 单元测试和测试用例 1.2 可通过的测试 1.3 不能通过的测试 1.4 测试未通过时怎么办 1.5 添加新测试 2 测试类 2.1 各种断言方法 2.2 一个要 ...

  7. 拒绝从入门到放弃_《Python 核心编程 (第二版)》必读目录

    目录 目录 关于这本书 必看知识点 最后 关于这本书 <Python 核心编程 (第二版)>是一本 Python 编程的入门书,分为 Python 核心(其实并不核心,应该叫基础) 和 高 ...

  8. python基础教程第二版和第三版哪个好-python基础教程 2版和3版哪个适合新手?!...

    python基础教程 2版和3版哪个适合新手? 现在学是学python3. 两者的差异发者本身影响并不大,个别语法细微的差比如python3的print数方式使用,一些常用模块的名称差异,一些机制的差 ...

  9. python核心编程第二版pdf_Python Book电子书pdf版合集 Python核心高级编程第二版

    1小时学会Python.doc 51CTO下载-[Python系列].BeginningPythonFromNovicetoProfessionalSecondEdition.pdf 8.Python ...

最新文章

  1. 世界人工智能创新大赛来了!
  2. localhost: Error: JAVA_HOME is not set. [Hadoop] Error: JAVA_HOME is not set
  3. Sql结果导出为excel文件
  4. 广东发展银行系统分析师面试问题
  5. android实现模拟自动点击_昆仑通态专题(十三):模拟实现全自动洗衣机系统的设计(案例)...
  6. 织梦dedecms小说网站源码|带采集+搭建方式
  7. python 修改列名_请教一个 Python 技巧(批量对 pandas.DataFrame()统一修改列名)
  8. Let’ s Encrypt 现支持通配符的 HTTPS 认证
  9. oracle group by
  10. java图片色差_java – JPEG图像的颜色错误
  11. 如何连接linux服务器
  12. 2021-08-06MATLAB深度学习简单应用
  13. 【华为认证考试扫盲】超详细的华为认证入门基础知识,考证必看。
  14. 计算机课反思的作文600字,中考反思作文600字6篇
  15. FITS python
  16. 内外兼修 高阶游戏鼠标达尔优A970黑武士评测
  17. 【精品教程】Android应用开发详解pdf分享
  18. 系统架构设计笔记(38)—— 工作流设计
  19. magento添加sku_快速提示:如何将优惠券添加到Magento电子商务商店
  20. chrome DevTools之黑箱大法(Blackbox )

热门文章

  1. 新手学习python(十七)mysql操作
  2. Mac 如何安装webpack
  3. “乒乓外交”和人脉扩展
  4. dp2:线性dp、区间dp、计数dp.
  5. 9.1 X射线衍射曲线绘制(project)
  6. 27岁3年社会经历 我对人生态度发生巨大的改变。 执帝都想转行了。
  7. 【脱离文档流的三种方法】
  8. 用CFileFind类实现的目录树遍历
  9. 乡镇纪委干部提升能力的方法
  10. 运营必看:网上商城的正确运营姿势