笔记转载于GitHub项目

https://github.com/NLP-LOVE/Introduction-NLP​github.com

12. 依存句法分析

语法分析(syntactic parsing )是自然语言处理中一个重要的任务,其目标是分析句子的语法结构并将其表示为容易理解的结构(通常是树形结构)。同时,语法分析也是所有工具性NLP任务中较为高级、较为复杂的一种任务。 通过掌握语法分析的原理、实现和应用,我们将在NLP工程师之路上跨越一道分水岭。 本章将会介绍短语结构树依存句法树两种语法形式,并且着重介绍依存句法分析的原理和实现。

12.1 短语结构树

语言其实具备自顶而下的层级关系,固定数量的语法结构能够生成无数句子。比如,仅仅利用下列两个语法规律,我们就能够生成所有名词短语。

  • 名词短语可以由名词和名词短语组成。
  • 名词短语还可以由名词和名词组成。

例如,“上海+浦东+机场+航站楼”,所以,汉语中大部分句子都可以通过这样的语法来生成。

在语言学中,这样的语法被称为上下文无关文法,它由如下组件构成:

  • 终结符结合 Σ,比如汉语的一个词表。
  • 非终结符集合 V,比如“名词短语”“动词短语”等短语结构组成的集合。V 中至少包含一个特殊的非终结符,即句子符或初始符,计作 S。
  • 推到规则 R,即推到非终结符的一系列规则: V -> V U Σ。

基于上下文无关文法理论,我们可以从 S 出发,逐步推导非终结符。一个非终结符至少产生一个下级符号,如此一层一层地递推下去,我们就得到了一棵语法树。但在NLP中,我们称其为短语结构树。也就是说,计算机科学中的术语“上下文无关文法”在语言学中被称作“短语结构语法”。

1.短语结构树

短语结构语法描述了如何自顶而下的生成一个句子,反过来,句子也可以用短语结构语法来递归的分解。层级结构其实是一种树形结构,例如这句话“上海 浦东 开发 与 法制 建设 同步”,分解成如下图的短语结构树:

这样的树形结构称为短语结构树,相应的语法称为*短语结构语法**或上下文无关文法。至于树中的字母下面开始介绍。

2.宾州树库和中文树库

语言学家制定短语结构语法规范,将大量句子人工分解为树形结构,形成了一种语料库,称为树库( treebank )。常见的英文树库有宾州树库,相应地,中文领域有CTB。上图中叶子节点(词语)的上级节点为词性,词性是非终结符的一种,满足“词性生成词语”的推导规则。

常见的标记如下:

但是由于短语结构语法比较复杂,相应句法分析器的准确率并不高,现在研究者绝大部分转向了另一种语法形式。

12.2 依存句法树

不同于短语结构树,依存句法树并不关注如何生成句子这种宏大的命题。依存句法树关注的是句子中词语之间的语法联系,并且将其约束为树形结构。

1.依存句法理论

依存语法理论认为词与词之间存在主从关系,这是一种二元不等价的关系。在句子中,如果一个词修饰另一个词,则称修饰词为从属词( dependent ),被修饰的词语称为支配词(head),两者之间的语法关系称为依存关系( dependency relation)。比如句子“大梦想”中形容词“大”与名词“梦想"之间的依存关系如图所示:

图中的箭头方向由支配词指向从属词,这是可视化时的习惯。将一个句子中所有词语的依存关系以有向边的形式表示出来,就会得到一棵树,称为依存句法树( dependency parse tree)。比如句子“弱小的我也有大梦想”的依存句法树如图所示。

现代依存语法中,语言学家 Robinson 对依存句法树提了 4 个约束性的公理。

  • 有且只有一个词语(ROOT,虚拟根节点,简称虚根)不依存于其他词语。
  • 除此之外所有单词必须依存于其他单词。
  • 每个单词不能依存于多个单词。
  • 如果单词 A 依存于 B,那么位置处于 A 和 B 之间的单词 C 只能依存于 A、B 或 AB 之间的单词。

这 4 条公理分别约束了依存句法树(图的特例)的根节点唯一性、 连通、无环和投射性( projective )。这些约束对语料库的标注以及依存句法分析器的设计奠定了基础。

2.中文依存句法树库

目前最有名的开源自由的依存树库当属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列,每行都是一个单词, 空白行表示句子结束。单元中的下划线 _ 表示空白, 结合其中一句样例,解释如表所示。

词性标注集合依存关系标注集请参考 UD 的官方网站:

http://niversaldependencies.org/guidelines.html

另一份著名的语料库依然是 CTB,只不过需要额外利用一些工具将短语结构树转换为依存句法树。读者可以直接下载转换后的 CTB 依存句法树库,其格式是类似于 CoNLl-U 的 CoNLL。

3.依存句法树的可视化

工具如下:

  • 南京大学汤光超开发的 Dependency Viewer。导入 .conll 扩展名的树库文件即可。
  • brat 标注工具。

可视化工具可以帮助我们理解句法树的结构,比较句子之间的不同。

12.3 依存句法分析

依存句法分析( dependency parsing )指的是分析句子的依存语法的一种中高级 NLP任务,其输人通常是词语和词性,输出则是一棵依存句法树。 本节介绍实现依存句法分析的两种宏观方法,以及依存句法分析的评价指标。

1.基于图的依存句法分析

正如树是图的特例一样,依存句法树其实是完全图的一个子图。如果为完全图中的每条边是否属于句法树的可能性打分,然后就可以利用 Prim 之类的算法找出最大生成树( MST )作为依存句法树了。这样将整棵树的分数分解( factorize )为每条边上的分数之和,然后在图上搜索最优解的方法统称为基于图的算法。

在传统机器学习时代,基于图的依存句法分析器往往面临运行开销大的问题。这是由于传统机器学习所依赖的特征过于稀疏,训练算法需要在整个图上进行全局的结构化预测等。考虑到这些问题,另一种基于转移的路线在传统机器学习框架下显得更加实用。

2.基于转移的依存句法分析

我们以“人 吃 鱼”这个句子为例子,手动构建依存句法树。

  • 从“吃”连线到“人”建立依存关系,主谓关系。
  • 从“吃”连线到“鱼”建立依存关系,动宾关系。

如此,我们将一棵依存句法树的构建过程表示为两个动作。如果机器学习模型能够根据句子的某些特征准确地预测这些动作,那么计算机就能够根据这些动作拼装出正确的依存句法树了。这种拼装动作称为转移( transition),而这类算法统称为基于转移的依存句法分析

12.4 基于转移的依存句法分析

1.Arc-Eager 转移系统

一个转移系统 S 由 4 个部件构成: S = (C,T,Cs,Ct),其中:

  • C 是系统状态的集合
  • T 是所有可执行的转移动作的集合。
  • Cs 是一个初始化函数
  • Ct 为一系列终止状态,系统进入该状态后即可停机输出最终的动作序列。

而系统状态又由 3 元祖构成: C = (σ,β,A) 其中:

  • σ 为一个存储单词的栈。
  • β 为存储单词的队列
  • A 为已确定的依存弧的集合。

Arc-Eager 转移系统的转移动作集合详见下表:

对于上面的“人 吃 鱼”案例,Arc-Eager 的执行步骤如下:

此时集合 A 中的依存弧为一颗依存句法树。

2.训练原理

对基于转移的依存句法分析器而言,它学习和预测的对象是一系列转移动作。然而依存句法树库是一棵树,并不是现成的转移动作序列。这时候就需要一个算法将语料库中的依存句法树转移为正确地转移动作序列。

这里可以使用感知机进行训练得到转移动作序列,原理详见:

《自然语言处理入门》--5.感知机分类与序列标注​mp.weixin.qq.com

训练句法分析器时,结构化感知机算法迭代式的优化线性模型,目标是使其将最高的分值赋予可抵达正确句法树的转移序列。

训练分为以下几个步骤:

  • 读入一个训练样本,提取特征,创建 ArcEager 的初始状态 c。
  • 若 c 不是终止状态,反复进行转移序列,修正参数。
  • 算法终止,返回返回模型参数 w。

12.5 依存句法分析 API

1.训练模型

本节使用的语料库是 CTB8.0,运行代码的时候会自动下载语料库: train_parser.py

https://github.com/NLP-LOVE/Introduction-NLP/tree/master/code/ch12/train_parser.py

训练时间比较长,结果如下:

1 人 人 N NN _ 2 nsubj _ _
2 吃 吃 V VV _ 0 ROOT _ _
3 鱼 鱼 N NN _ 2 dobj _ _
UAS=83.3% LAS=81.0%

2.标准化评测

给定两棵树,一棵树为标准答案(来自测试集),一棵树为预测结果,评测的目标是衡量这两棵树的差异。如果将树的节点编号,拆解为依存弧并分别存入两个集合 A ( 标准答案)和 B (预测结果),则可以利用分类任务的 F1 评价指标。

依存句法分析任务采用的评测指标为 UAS (unlabeled atachment score) 和 LAS (labeled attachment score ),分别对应忽略标签和包括标签的 F1 值。以 LAS 为例,具体计算方式如下:

UAS 的计算也是同理,只不过将每条依存弧上的标签去掉后放人集合参与运算即可。相较于 LAS, UAS 仅仅衡量支配词的预测准确率,不衡量依存关系的准确率,一般分数更高。

在上面的训练模型中已经做了评测

UAS=83.3% LAS=81.0%

这个分数说明,在测试集上有 83% 的支配词被准确预测,有 81% 的依存弧被准确预测。

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 (名词性主语)。

1.利用这一规律, 不难写出第一版遍历算法, 也就是用个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)

结果如下:

第一版
电池 = 棒
机身 = 长
分辨率 = 高

2.虽然的确提取出了一些意见,然而后两个都是错误的。这一版算法存在的问题之一是没有考虑到“机身不长””“分辨率不高"等否定修饰关系。否定修饰关系在依存句法中的标记为 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)

结果如下:

第二版
电池 = 棒
机身 = 不长
分辨率 = 不高

3.接下来思考如何提取“待机”的意见,“待机”与“长”之间的公共父节点为“是”,于是我们得到第三版算法如下:

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 个属性被完整正确地提取出来了,读者可以尝试搜集更多的句子,通过分析句法结构总结更多的提取规则。

系列文章

ROST情感分析的语法规则_《自然语言处理入门》12.依存句法分析--提取用户评论...相关推荐

  1. 情感分析朴素贝叶斯_朴素贝叶斯推文的情感分析

    情感分析朴素贝叶斯 Millions of tweets are posted every second. It helps us know how the public is responding ...

  2. python评论情感分析计算分数值_使用python对淘宝评论进行情感分析并绘制词云

    淘宝商品评论分析系统简介 截至2018年12月,我国网络购物用户规模达6.10亿,网购已经慢慢占据了我们生活的方方面面,所以一份透明的网购指南就显得尤为重要. 大部分网购消费群体只能依赖于其他人在商品 ...

  3. 情感分析Sentiment Analysis 知识资料全集(入门/进阶/论文/综述/视频/专家,附查看

    情感分析 ( Sentiment Analysis ) 专知荟萃 入门学习 进阶论文 Tutorial 综述 代码 视频教程 领域专家 入门学习 斯坦福大学自然语言处理第七课"情感分析(Se ...

  4. 自然语言处理(NLP)之依存句法分析的可视化及图分析

    依存句法分析的效果虽然没有像分词.NER的效果来的好,但也有其使用价值,在日常的工作中,我们免不了要和其打交道.如何分析依存句法分析的结果,一个重要的方面便是其可视化和它的图分析. 我们使用的NLP工 ...

  5. mysql 名次语法规则_基于sql语句的一些常用语法积累总结

    1.当某一字段的值希望通过其它字值显示出来时(记录转换),可通过下面的语句实现:case Type when '1' then '普通通道' when '2' then '高端通道' end as T ...

  6. matlab的基本语法规则_【经验交流】matlab自定义回调函数语法规则

    给出我今天学到的两个例子来说明两种用法: (1)set(h, 'StartFcn', @myfile)型 function [varargout] = XIE_bwmorphfig(Size, var ...

  7. python和nltk自然语言处理书评_python自然语言处理_自然语言处理入门

    说明:本文是<Python数据分析与数据化运营>中的"3.12.4 自然语言文本预处理".下面是正文内容-与数据库 本文从概念和实际操作量方面,从零开始,介绍在Pyth ...

  8. 自然语言处理之文本情感分析

    1.导语 深度学习近些年取得突破性的发展,目前深度学习技术在人工智能领域应用最广泛的两方面就是CV(计算机视觉)和NLP(自然语言处理),在本次夏虹老师的<人工智能>课程上,我和我的小组成 ...

  9. AI Challenger 2018:细粒度用户评论情感分析冠军思路总结

    2018年8月-12月,由美团点评.创新工场.搜狗.美图联合主办的"AI Challenger 2018全球AI挑战赛"历经三个多月的激烈角逐,冠军团队从来自全球81个国家.100 ...

  10. 实体词典 情感词典_人工智能技术落地:情感分析概述

    从自然语言处理技术的角度来看,情感分析的任务是从评论的文本中提取出评论的实体,以及评论者对该实体所表达的情感倾向,自然语言所有的核心技术问题.因此,情感分析被认为是一个自然语言处理的子任务. 情感分析 ...

最新文章

  1. java date 格式化_3种 Springboot 全局时间格式化方式,别再写重复代码了
  2. struts2+hibernate3+spring3(ssh2)框架下的web应用(1)
  3. 牛客网 二叉树的层序遍历
  4. IT牛人往事如烟之七大“先烈”
  5. c++ 的makefile文件实例
  6. linux mv命令改名,Linux mv命令:移动文件或改名
  7. 一步一步做搜索(一)
  8. ASP.NET 封装JS文件到DLL中并在页面中调用
  9. USACO 2.3 Cow Pedigrees 【DP+前缀和优化】
  10. opencv摄像头拍摄视频并保存方法
  11. IntelliJ IDEA设置--类代码模板自定义(注释)
  12. AD7124源码 兼容AD7124-4/8 代码都经过验证 有验证的项目PCB图
  13. android程序卡死无响应,Android程序未响应(ANR)问题
  14. Scroller简单介绍
  15. sourctree Commit merged changes immediately选项解读
  16. [MacBook Pro] 错误提示zsh_ command not found_ brew
  17. Unity AzureKinect Ar贴纸
  18. 什么是PEP8编码风格?
  19. 英文网站针对google优化用阿里云dns好吗?
  20. 离开学校怎样自学修炼成为一名网页设计师(四)

热门文章

  1. 软件测试中测试用例的简单案例
  2. Matlab 2018a的安装步骤
  3. 年末优质蓝牙耳机盘点:十款商城热销高人气无线蓝牙耳机测评
  4. JavaSE 字符串
  5. 项目管理工具project软件学习(四) - 日历保存为模板、日历重命名、删除
  6. iconv linux 开源代码,每天一个 Linux 命令(123):iconv 命令
  7. 音乐网站源码:Spring Boot + MyBatis + Vue 实现的
  8. Java程序设计教程(第3版)雍俊海 全书例程-1
  9. 程序设计与c语言区别,c语言程序设计和c程序设计有什么区别啊
  10. CCNA 中文教材 (pdf)