跳转至

依存分析与依存树 dependency parse

句法是指句子的各个组成部分的相互关系,句法分析分为句法结构分析(syntactic structure parsing)和依存关系分析(dependency parsing)。句法结构分析用于获取整个句子的句法结构,依存分析用于获取词汇之间的依存关系,目前的句法分析已经从句法结构分析转向依存句法分析。

依存语法通过分析语言单位内成分之间的依存关系揭示其句法结构,主张句子中核心动词是支配其它成分的中心成分,而它本身却不受其它任何成分的支配,所有受支配成分都以某种依存关系从属于支配者。

在20世纪70年代,Robinson提出依存语法中关于依存关系的四条公理:

  1. 一个句子中只有一个成分是独立的;
  2. 其它成分直接依存于某一成分;
  3. 任何一个成分都不能依存与两个或两个以上的成分;
  4. 如果A成分直接依存于B成分,而C成分在句中位于A和B之间,那么C或者直接依存于B,或者直接依存于A和B之间的某一成分;

一,依存关系

依存关系是一个中心词与其从属之间的二元非对称关系,一个句子的中心词通常是动词(Verb),所有其他词要么依赖于中心词,要么通过依赖路径与它关联。

nlp-dependency-parsing_1.png

1,依存关系

依存结构是加标签的有向图,箭头从中心词指向从属,具体来说,箭头是从head指向child,从该解析树可以看出,每个Token只有一个Head。

2,关系标签

标签表示从属的语法功能,名词性的标签是:

  • root:中心词,通常是动词
  • nsubj:名词性主语(nominal subject)
  • dobj:直接宾语(direct object)
  • prep:介词
  • pobj:介词宾语
  • cc:连词

其他常用的标签:

  • compound:复合词
  • advmod:状语
  • det:限定词
  • amod:形容词修饰语

二,解析依存关系

SpaCy能够快速准确地解析句子的依存关系,并且具有丰富的API用于导航依存关系树,SpaCy使用head和child来描述依存关系中的连接,识别每个Token的依存关系:

  • token.text:token的文本
  • token.head:当前Token的Parent Token,从语法关系上来看,每一个Token都只有一个Head。
  • token.dep_:依存关系
  • token.children:语法上的直接子节点
  • token.ancestors:语法上的父节点
  • _pos:词性
  • _tag:词性

让我使用SpaCy来对句子进行依存分析:

1
2
3
4
5
6
import spacy

nlp = spacy.load('en')
doc = nlp( "spaCy uses the terms head and child to describe the words" )
for token in doc:
    print('{0}({1}) <-- {2} -- {3}({4})'.format(token.text, token.tag_, token.dep_, token.head.text, token.head.tag_))

打印每个Token的依存关系和head节点,箭头表示从属关系,得到的结果是:

spaCy(NNP) <-- nsubj -- uses(VBZ)
uses(VBZ) <-- ROOT -- uses(VBZ)
the(DT) <-- det -- head(NN)
terms(NNS) <-- compound -- head(NN)
head(NN) <-- dobj -- uses(VBZ)
and(CC) <-- cc -- head(NN)
child(NN) <-- conj -- head(NN)
to(TO) <-- aux -- describe(VB)
describe(VB) <-- xcomp -- uses(VBZ)
the(DT) <-- det -- words(NNS)
words(NNS) <-- dobj -- describe(VB)

也可以使用display来显示依存关系,在浏览器中输入 http://localhost:5000 显示依存结构:

1
2
3
4
5
6
import spacy
from spacy import displacy

nlp = spacy.load('en')
doc = nlp( "spaCy uses the terms head and child to describe the words" )
displacy.serve(doc, style='dep')

三, 依存树的来龙去脉及用法

来历

a. 简单的短语分词 (正向逆向最大匹配,n-gram,机器学习...)(以单个词为重点)

比如: 猴子喜欢吃香蕉。->猴子 喜欢 吃 香蕉 。

b. 由分词转向词性标注

猴子/NN 喜欢/VV 吃/VV 香蕉/NN 。/PU

(但是能不能站在句子上分析呢?就有了下面的发展)

c. 由词性标注生成短语句法树 (从整个句子分析)

nlp-dependency-tree_1.jpeg

短语句法树的计算机表示

nlp-dependency-tree_2.jpeg

短语句法树的逻辑表示

d.由短语句法树转成依存树(依存关系可以用树形图表示,表示依存关系的树形图称为依存树dependency tree)

转换的依存树长这个样子:

nlp-dependency-tree_3.jpeg

转换的依存树长这个样子:

nlp-dependency-tree_4.jpeg

依存投射树 nlp-dependency-tree_5.jpeg

但是计算机中肯定就不是这么存的了。比如Stanford Parser 是这个样子的: Stanford Parser Dependency Tree nlp-dependency-tree_6.jpeg

这里的数字是这个词的序列: 猴子 -1,喜欢-2,吃-3,香蕉-4 (符号被抛弃)

比如:nsubj ( 喜欢-2,猴子-1) nsubj是表示后两者的关系,这里前者是父亲,后者是儿子,也就是 猴子 依存于 喜欢 。

两个基本问题

都挺简单的数据结构问题(多叉树的节点问题): a. 已知一个节点怎么找到它的父(子)节点。 b. 求两个节点的最短路径 就是找到一个节点,把自己和所有父节点放到一个数组里,再在另一个节点,从本身开始顺着父节点找,直到找到和第一个节点并且存在于第一个数组里,这样,第一个数组从0开始到这个公共节点和第二个节点的从这个节点到自己本身的所有节点就是这俩节点的最短路径。

举个实在例子(意见抽取):

nlp-dependency-tree_7.jpeg

dependency tree是: nlp-dependency-tree_8.jpeg nlp-dependency-tree_9.jpeg

属性之间的最短路径: nlp-dependency-tree_10.jpeg

注意的是,这个路径上每次经过的线(也就是他们俩的关系),这里的路径就是这个。 属性与评价之间的最短路径: nlp-dependency-tree_11.jpeg

从这两组最短路径很明显看出谁跟谁更亲近,这也是最短路径的一个应用。

应用

  • 短语缩句
  • 提取文本主要内容
  • 文本分类
  • 情感分析
  • 意见抽取等

参考文档:

Complete Guide to spaCy

SpaCy Dependency Parse