《自然语言处置惩罚入门》12.依存句法分析–提取用户批评
12. 依存句法剖析
语法剖析(syntactic parsing )是自然言语处置惩罚中一个主要的使命,其目的是剖析句子的语法构造并将其示意为轻易明白的构造(通常是树形构造)。同时,语法剖析也是一切东西性NLP使命中较为高等、较为庞杂的一种使命。 经由历程控制语法剖析的道理、完成和运用,我们将在NLP工程师之路上逾越一道分水岭。 本章将会引见短语构造树和依存句法树两种语法情势,而且偏重引见依存句法剖析的道理和完成。
12.1 短语构造树
言语实在具有自顶而下的层级关联,牢固数目的语法构造能够生成无数句子。比方,仅仅应用以下两个语法规律,我们就能够生成一切名词短语。
- 名词短语能够由名词和名词短语组成。
- 名词短语还能够由名词和名词组成。
比方,“上海+浦东+机场+航站楼”,所以,汉语中大部份句子都能够经由历程如许的语法来生成。
在言语学中,如许的语法被称为上下文无关文法,它由以下组件组成:
- 终结符连系 Σ,比方汉语的一个词表。
- 非终结符鸠合 V,比方“名词短语”“动词短语”等短语构造组成的鸠合。V 中最少包含一个特别的非终结符,即句子符或初始符,计作 S。
- 推到划定规矩 R,即推到非终结符的一系列划定规矩: V -> V U Σ。
基于上下文无关文法理论,我们能够从 S 动身,逐渐推导非终结符。一个非终结符最少发生一个下级标记,云云一层一层地递推下去,我们就获得了一棵语法树。但在NLP中,我们称其为短语构造树。也就是说,盘算机科学中的术语“上下文无关文法”在言语学中被称作“短语构造语法”。
- 短语构造树短语构造语法形貌了怎样自顶而下的生成一个句子,反过来,句子也能够用短语构造语法来递归的剖析。层级构造实际上是一种树形构造,比方这句话“上海 浦东 开发 与 法制 竖立 同步”,剖析成以下图的短语构造树:
如许的树形构造称为短语构造树,响应的语法称为*短语构造语法**或上下文无关文法。至于树中的字母下面入手下手引见。
- 宾州树库和中文树库言语学家制订短语构造语法范例,将大批句子人工剖析为树形构造,形成了一种语料库,称为树库( treebank )。罕见的英文树库有宾州树库,响应地,中文范畴有CTB。上图中叶子节点(词语)的上级节点为词性,词性黑白终结符的一种,满足“词性生成词语”的推导划定规矩。
罕见的标记以下:
标记 释义 IP-HLN 单句-标题 NP-SBJ 名词短语-主语 NP-PN 名词短语-代词 NP 名词短语 VP 动词短语 然则因为短语构造语法比较庞杂,响应句法剖析器的准确率并不高,如今研究者绝大部份转向了另一种语法情势。
12.2 依存句法树
差别于短语构造树,依存句法树并不关注怎样生成句子这类远大的命题。依存句法树关注的是句子中词语之间的语法联络,而且将其束缚为树形构造。
- 依存句法理论依存语法理论以为词与词之间存在主从关联,这是一种二元不等价的关联。在句子中,假如一个词润饰另一个词,则称润饰词为隶属词( dependent ),被润饰的词语称为安排词(head),两者之间的语法关联称为依存关联( dependency relation)。比方句子“大妄想”中形容词“大”与名词“妄想"之间的依存关联如图所示:
图中的箭头方向由安排词指向隶属词,这是可视化时的习气。将一个句子中一切词语的依存关联以有向边的情势示意出来,就会获得一棵树,称为依存句法树( dependency parse tree)。比方句子“微小的我也有大妄想”的依存句法树如图所示。
当代依存语法中,言语学家 Robinson 对依存句法树提了 4 个束缚性的正义。
- 有且只要一个词语(ROOT,假造根节点,简称虚根)不依存于其他词语。
- 除此之外一切单词必需依存于其他单词。
- 每一个单词不能依存于多个单词。
- 假如单词 A 依存于 B,那末位置处于 A 和 B 之间的单词 C 只能依存于 A、B 或 AB 之间的单词。
这 4 条正义离别束缚了依存句法树(图的惯例)的根节点唯一性、 连通、无环和投射性( projective )。这些束缚对语料库的标注以及依存句法剖析器的设想奠基了基本。
- 中文依存句法树库现在最有名的开源自在的依存树库当属UD ( Universal Dependencies),它以“签名-非商业性运用-雷同体式格局同享4.0”等相似协定免费向民众受权。UD是个跨语种的语法标注项目,一共有 200 多名贡献者为 70 多种言语标注了 100 多个树库。详细到中文,存在4个差别范畴的树库。本章拔取个中范围最大的 UD_ Chinese GSD 作为示例。该树库的语种为繁体中文,将其转换为简体中文后,供人人下载运用。
http://file.hankcs.com/corpus/chs-gsd-ud.zip
该树库的花样为 CoNLL-U,这是一种以制表符分开的表格花样。CoNLL-U 文件有10列,每行都是一个单词, 空缺行示意句子完毕。单位中的下划线 _ 示意空缺, 连系个中一句样例,诠释如表所示。
另一份有名的语料库依然是 CTB,只不过须要分外应用一些东西将短语构造树转换为依存句法树。读者能够直接下载转换后的 CTB 依存句法树库,其花样是相似于 CoNLl-U 的 CoNLL。
- 依存句法树的可视化东西以下:
- 南京大学汤光超开发的 Dependency Viewer。导入 .conll 扩展名的树库文件即可。
- brat 标注东西。
可视化东西能够协助我们明白句法树的构造,比较句子之间的差别。
12.3 依存句法剖析
依存句法剖析( dependency parsing )指的是剖析句子的依存语法的一种中高等 NLP使命,其输人通常是词语和词性,输出则是一棵依存句法树。 本节引见完成依存句法剖析的两种宏观要领,以及依存句法剖析的评价目标。
- 基于图的依存句法剖析正如树是图的惯例一样,依存句法树实际上是完全图的一个子图。假如为完全图中的每条边是不是属于句法树的可能性打分,然后就能够应用 Prim 之类的算法找出最大生成树( MST )作为依存句法树了。如许将整棵树的分数剖析( factorize )为每条边上的分数之和,然后在图上搜刮最优解的要领统称为基于图的算法。
在传统机械进修时期,基于图的依存句法剖析器每每面对运转开支大的问题。这是因为传统机械进修所依靠的特性过于希罕,练习算法须要在全部图上举行全局的构造化展望等。考虑到这些问题,另一种基于转移的线路在传统机械进修框架下显得越发有用。
- 基于转移的依存句法剖析我们以“人 吃 鱼”这个句子为例子,手动构建依存句法树。
- 从“吃”连线到“人”竖立依存关联,主谓关联。
- 从“吃”连线到“鱼”竖立依存关联,动宾关联。
云云,我们将一棵依存句法树的构建历程示意为两个行动。假如机械进修模子能够依据句子的某些特性准确地展望这些行动,那末盘算机就能够依据这些行动拼装出准确的依存句法树了。这类拼装行动称为转移( transition),而这类算法统称为基于转移的依存句法剖析。
12.4 基于转移的依存句法剖析
- Arc-Eager 转移体系一个转移体系 S 由 4 个部件组成: S = (C,T,Cs,Ct),个中:
- C 是体系状况的鸠合
- T 是一切可实行的转移行动的鸠合。
- Cs 是一个初始化函数
- Ct 为一系列停止状况,体系进入该状况后即可停机输出终究的行动序列。
而体系状况又由 3 元祖组成: C = (σ,β,A) 个中:
- σ 为一个存储单词的栈。
- β 为存储单词的行列
- A 为已肯定的依存弧的鸠合。
Arc-Eager 转移体系的转移行动鸠合详见下表:
行动称号 前提 诠释 Shift 行列 β 非空 将队首单词 i 压栈 LeftArc 栈顶单词 i 没有安排词 将栈顶单词 i 的安排词设为队首单词 j,即 i 作为 j 的子节点 RightArc 队首单词 j 没有安排词 将队首单词 j 的安排词设为栈顶单词 i,即 j 作为 i 的子节点 Reduce 栈顶单词 i 已有安排词 将栈顶单词 i 出栈 关于上面的“人 吃 鱼”案例,Arc-Eager 的实行步骤以下:
装填编号 σ 转移行动 β A 0 [] 初始化 [人,吃,鱼,虚根] {} 1 [人] Shift [吃,鱼,虚根] {} 2 [] LeftArc(主谓) [吃,鱼,虚根] ({人xleftarrow{主谓}吃}) 3 [吃] Shift [鱼,虚根] ({人xleftarrow{主谓}吃}) 4 [吃,鱼] RightArc(动宾) [虚根] ({人xleftarrow{主谓}吃,吃xrightarrow{动宾}鱼}) 5 [吃] Reduce [虚根] ({人xleftarrow{主谓}吃,吃xrightarrow{动宾}鱼}) 6 [] LeftArc(中心) [虚根] ({人xleftarrow{主谓}吃,吃xrightarrow{动宾}鱼,吃xleftarrow{中心}虚根}) 此时鸠合 A 中的依存弧为一颗依存句法树。
- 练习道理对基于转移的依存句法剖析器而言,它进修和展望的对象是一系列转移行动。但是依存句法树库是一棵树,并非现成的转移行动序列。这时候刻就须要一个算法将语料库中的依存句法树转移为准确地转移行动序列。
这里能够运用感知机举行练习获得转移行动序列,道理详见:
5. 感知机分类与序列标注
练习句法剖析器时,构造化感知机算法迭代式的优化线性模子,目的是使其将最高的分值给予可到达准确句法树的转移序列。
练习分为以下几个步骤:
- 读入一个练习样本,提取特性,建立 ArcEager 的初始状况 c。
- 若 c 不是停止状况,重复举行转移序列,修改参数。
- 算法停止,返回返回模子参数 w。
12.5 依存句法剖析 API
- 练习模子本节运用的语料库是 CTB8.0,运转代码的时刻会自动下载语料库: train_parser.py
练习时间比较长,效果以下:
1 人 人 N NN _ 2 nsubj _ _ 2 吃 吃 V VV _ 0 ROOT _ _ 3 鱼 鱼 N NN _ 2 dobj _ _ UAS=83.3% LAS=81.0%
- 标准化评测给定两棵树,一棵树为标准答案(来自测试集),一棵树为展望效果,评测的目的是权衡这两棵树的差别。假如将树的节点编号,拆解为依存弧并离别存入两个鸠合 A ( 标准答案)和 B (展望效果),则能够应用分类使命的 F1 评价目标。
依存句法剖析使命采纳的评测目标为 UAS (unlabeled atachment score) 和 LAS (labeled attachment score ),离别对应疏忽标签和包含标签的 F1 值。以 LAS 为例,详细盘算体式格局以下:
[ P=frac{|Acap B|}{|B|} R=frac{|Acap B|}{|A|} LAS=frac{2*P*R}{P+R} ]
UAS 的盘算也是同理,只不过将每条依存弧上的标签去掉后放人鸠合介入运算即可。相较于 LAS, UAS 仅仅权衡安排词的展望准确率,不权衡依存关联的准确率,平常分数更高。在上面的练习模子中已做了评测
UAS=83.3% LAS=81.0%
这个分数申明,在测试集上有 83% 的安排词被准确展望,有 81% 的依存弧被准确展望。
笔记转载于GitHub项目:https://github.com/NLP-LOVE/Introduction-NLP
12.6 案例: 基于依存句法剖析的看法抽取
实在许多人都有一个疑问,依存句法剖析终究能够用来干什么。本节就来应用依存句法剖析完成一个看法抽取的例子,提取以下商品批评中的属性和买家评价。
电池异常棒,机身不长,长的是待机,然则屏幕分辨率不高。
为了提取“电池”“机身”“待机”和“分辨率”所对应的看法,质朴的处置惩罚体式格局是在分司和词性标注以后编写正则表达式,提取名词背面的形容词。但是正则表达式没法处置惩罚“长的是待机”如许句式天真的例子。
这时候就能够对这句话举行依存句法剖析,剖析代码以下:
from pyhanlp import *
CoNLLSentence = JClass('com.hankcs.hanlp.corpus.dependency.CoNll.CoNLLSentence')
CoNLLWord = JClass('com.hankcs.hanlp.corpus.dependency.CoNll.CoNLLWord')
IDependencyParser = JClass('com.hankcs.hanlp.dependency.IDependencyParser')
KBeamArcEagerDependencyParser = JClass('com.hankcs.hanlp.dependency.perceptron.parser.KBeamArcEagerDependencyParser')
parser = KBeamArcEagerDependencyParser()
tree = parser.parse("电池异常棒,机身不长,长的是待机,然则屏幕分辨率不高。")
print(tree)
运转效果以下:
1 电池 电池 N NN _ 3 nsubj _ _
2 异常 异常 A AD _ 3 advmod _ _
3 棒 棒 V VA _ 0 ROOT _ _
4 , , P PU _ 3 punct _ _
5 机身 机身 N NN _ 7 nsubj _ _
6 不 不 A AD _ 7 neg _ _
7 长 长 V VA _ 3 conj _ _
8 , , P PU _ 7 punct _ _
9 长 长 V VA _ 11 top _ _
10 的 的 D DEC _ 9 cpm _ _
11 是 是 V VC _ 7 conj _ _
12 待机 待机 N NN _ 11 attr _ _
13 , , P PU _ 3 punct _ _
14 然则 然则 A AD _ 18 advmod _ _
15 屏幕 屏幕 N NN _ 16 nn _ _
16 分辨率 分辨率 N NN _ 18 nsubj _ _
17 不 不 A AD _ 18 neg _ _
18 高 高 V VA _ 3 conj _ _
19 。 。 P PU _ 3 punct _ _
举行可视化后:
仔细观察,不难发明“电池”与“棒”、“机身”与“长”、“分辨率”与“高”之间的依存关联都是 nsubj (名词性主语)。
- 应用这一规律, 不难写出初版遍历算法, 也就是用个for 轮回去遍历树中的每一个节点。关于算法遍历树中的每一个词语, 假如其词性为名词且作为某个形容词的名词性主语,则以为该名词是属性,而形容词是看法。运转代码以下:
def extactOpinion1(tree): for word in tree.iterator(): if word.POSTAG == "NN" and word.DEPREL == "nsubj": print("%s = %s" % (word.LEMMA, word.HEAD.LEMMA)) print("初版") extactOpinion1(tree)
效果以下:
初版 电池 = 棒 机身 = 长 分辨率 = 高
- 虽然确实提取出了一些看法,但是后两个都是毛病的。这一版算法存在的问题之一是没有考虑到“机身不长””“分辨率不高"等否认润饰关联。否认润饰关联在依存句法中的标记为 neg,因而我们只需搜检形容词是不是存在否认润饰的安排词即可。因而得出第二版算法:
def extactOpinion2(tree): for word in tree.iterator(): if word.POSTAG == "NN" and word.DEPREL == "nsubj": if tree.findChildren(word.HEAD, "neg").isEmpty(): print("%s = %s" % (word.LEMMA, word.HEAD.LEMMA)) else: print("%s = 不%s" % (word.LEMMA, word.HEAD.LEMMA)) print("第二版") extactOpinion2(tree)
效果以下:
第二版 电池 = 棒 机身 = 不长 分辨率 = 不高
- 接下来思索怎样提取“待机”的看法,“待机”与“长”之间的大众父节点为“是”,因而我们获得第三版算法以下:
def extactOpinion3(tree): for word in tree.iterator(): if word.POSTAG == "NN": # 检测名词词语的依存弧是不是是“属性关联”, # 假如是,则寻觅安排词的子节点中的主题词 # 以该主题词作为名词的看法。 if word.DEPREL == "nsubj": # ①属性 if tree.findChildren(word.HEAD, "neg").isEmpty(): print("%s = %s" % (word.LEMMA, word.HEAD.LEMMA)) else: print("%s = 不%s" % (word.LEMMA, word.HEAD.LEMMA)) elif word.DEPREL == "attr": top = tree.findChildren(word.HEAD, "top") # ②主题 if not top.isEmpty(): print("%s = %s" % (word.LEMMA, top.get(0).LEMMA)) print("第三版") extactOpinion3(tree)
效果以下:
第三版 电池 = 棒 机身 = 不长 待机 = 长 分辨率 = 不高
至此,4 个属性被完全准确地提取出来了,读者能够尝试汇集更多的句子,经由历程剖析句法构造总结更多的提取划定规矩。
12.7 GitHub
HanLP何晗--《自然言语处置惩罚入门》笔记:
项目延续更新中......