想象你面前摆着一套乐高城堡积木,有屋顶、城墙、小旗子,但它们是散装的。说明书告诉你:屋顶要卡在城墙上,城墙要立在地基上,小旗子插在塔尖。正在学中文的机器人和你面对同样的问题——它读到“可爱小猫吃鱼”时,看到的只是一串从左到右的词语,这些词谁和谁是搭档?哪个是核心动作?哪个在修饰谁?如果机器人搞不懂这些,它就无法判断“吃鱼的是小猫”而不是“鱼吃小猫”。 依存解析(Dependency Parsing)就是给机器人看的“乐高说明书阅读技巧”:让计算机找出句子中词与词之间的“卡扣关系”,判定谁是支配者、谁是从属者,再给每对关系贴一个标签(主谓、动宾、定中……)。一旦摸清了这些关系,机器就能画出整句话的“骨骼图”——一棵以核心动作词为根、向外伸展的依存树。这棵树是无数 NLP 任务的起点:情感分析要确认“不好看”修饰的是哪个对象,信息抽取要挖出“谁对谁做了什么事”,机器翻译要借助它调整语序。 接下来,我们就用“搭乐高”这条故事线,从零认识依存解析:它是什么、有哪些关系类型、依存树长什么样、机器怎么自动搭建、有哪些现成工具、搭完能干什么、它又怕什么。读完你会明白,这棵小小的“词之树”,是让机器理解人类语言的重要地基。

岗位关联

依存解析是 NLP 文本预处理的关键枢纽,所有做情感分析、信息抽取、知识图谱的 AI 工程师都绕不开它,掌握它等于握住了机器理解句子的钥匙。

目录
  1. 可视化演示
  2. 名词解释:什么是依存解析
  3. 核心关系:主谓宾定状
  4. 句子骨骼:依存树结构
  5. 构建方法:自动搭建算法
  6. 经典工具:现成流水线
  7. 常见应用:搭完有何用
  8. 日常局限:乐高也怕卡壳
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

\u5c55\u793aRound Robin\u8c03\u5ea6\u7b97\u6cd5\u6309\u65f6\u95f4\u7247\u8f6e\u8f6c\u6267\u884c\u8fdb\u7a0b\u7684\u8fc7\u7a0b\uff0c\u6bcf\u4e2a\u8fdb\u7a0b\u83b7\u5f97\u56fa\u5b9a\u65f6\u95f4\u7247\uff0c\u7528\u5c3d\u540e\u8fdb\u5165\u5c31\u7eea\u961f\u5217\u7b49\u5f85\u3002

本节配有交互动效(进入视口后自动加载,约 3KB)。

Round Robin\u8c03\u5ea6 P1 P2 P3 P4 q=3 \u65f6\u95f4\u7247\u8f6e\u8f6c\u8c03\u5ea6

名词解释:什么是依存解析

在乐高世界里,每块积木的底部都有卡扣槽,顶上都有凸点,组装的关键就是找到“谁卡进谁”。句子也一样,词与词之间存在“卡扣”关系——有些词是“主人”,有些词是“随从”。比如“可爱小猫吃鱼”里,“吃”是发号施令的主人,它决定了“小猫”和“鱼”的站位;“可爱”则是“小猫”的装饰性随从。

这个概念在语言学中叫“依存关系”(Dependency Relation)。计算机要从一句话所有可能的词对中,找出哪些词真的存在这种主从关联,并画出有向弧。给出定义:如果词 $w_i$ 依存于词 $w_j$,那么 $w_j$ 是 $w_i$ 的支配词(父节点),$w_i$ 是从属词(子节点),记作 $\text{dep}(w_i) = w_j$。

这套思路与传统的“短语结构语法”不同——短语结构语法像把积木先分成一盒盒小套装(名词短语、动词短语),再组合;依存解析则直接关注“每一块积木最终卡在谁身上”,不搞中间包装。对机器来说,依存关系更容易计算,也更贴近语义角色:主语、宾语、修饰语直接从弧上读出来。

回到乐高上:每块“从属积木”都明确知道自己要卡在哪块“支配积木”上,整句话的组装关系就彻底清晰了。这就是依存解析的第一课——谁是主人,谁是随从。

dep(wi)=wj\text{dep}(w_i) = w_j
这个式子的意思是:词 $w_i$ 有一个“顶头上司” $w_j$。$w_i$ 听命于 $w_j$,就像一块积木卡在另一块积木上。
  1. 支配词(父节点)$w_j$ 是 $w_i$ 依赖的支配词,也就是它的“顶头上司”。
    wj=head(wi)w_j = \text{head}(w_i)
  2. 从属词(子节点)$w_i$ 是从属词,它依附于 $w_j$,是关系中的“随从”。
    wi=dependent(wj)w_i = \text{dependent}(w_j)
  3. 有向弧可视化从支配词 $w_j$ 画一条箭头指向从属词 $w_i$,弧线贴上关系标签。
    wj→wiw_j \rightarrow w_i

核心关系:主谓宾定状

乐高的卡扣分很多种:长条卡扣连接城墙,十字卡扣固定车轮,圆点卡扣拼接屋顶。依存关系也一样,不同的“卡扣”用不同的标签命名。最常用的标注体系叫 UD(Universal Dependencies,通用依存标注体系),它就像乐高官方的零件命名手册,让全球玩家用同一种语言描述组装关系。

最核心的几种关系:nsubj(主谓关系)标注“小猫 ← 吃”中“小猫”是主语;obj(动宾关系)标注“吃 → 鱼”中“鱼”是宾语;det(限定词)对应“the cat“中的”the“;amod(定中关系)对应”可爱小猫“中”可爱“修饰”小猫“;advmod(状中关系)对应”非常快“中”非常“修饰”快”。

用一个紧凑的记号把两个词和一个标签打包:如果词 $w_i$ 和 $w_j$ 之间存在某类关系 $r$,就记作 $\text{label}(w_i, w_j) = r$。注意这里的关系是有方向的——“小猫”和“吃”之间,标签是 nsubj,方向是从核心“吃”指向从属“小猫”。方向反了,主谓就变成了“谓主”,句子语义就崩了。

搞懂这套标签系统,就像学会了乐高说明书上的图例。以后你看到任何一串“词-词-标签”的组合,都能立即脑补出积木是怎么咬合的。

label(wi,wj)=r\text{label}(w_i, w_j) = r
关系标签 $r$ 告诉我们两个词之间的“卡扣类型”:是上下级(主谓)、动作对象(动宾),还是装饰关系(定中/状中)。
  1. 关系标签$r$ 是这个依存弧的语义标签,比如 nsubj、obj、amod。
    r=deprel(wi,wj)r = \text{deprel}(w_i, w_j)
  2. 标签集合$r$ 必须来自预定义的 UD 标签集合,不能随意造词。
    r∈{nsubj,obj,det,amod,advmod,… }r \in \{\text{nsubj}, \text{obj}, \text{det}, \text{amod}, \text{advmod}, \dots\}
  3. 方向性标签记录的是从支配词看向从属词的语义角色,方向改变则语义改变。
    label(wi,wj)≠label(wj,wi)\text{label}(w_i, w_j) \neq \text{label}(w_j, w_i)

句子骨骼:依存树结构

把一句话的所有依存弧画在一张图上,你会得到一棵倒挂的树:顶部是唯一的老大(根节点),往下分出树枝,每根树枝再分叉。乐高说明书的封面就是这样的成品图——城堡尖顶在最上方,墙壁和地基依次向下承托。依存树里,“根节点”通常由核心谓语动词担任,比如“可爱小猫吃鱼”的根就是“吃”。

树的规矩很严格:每个词(除了根)有且只有一个父节点,但可以有多个子节点;所有节点通过有向弧连接,不能有回路。也就是说,整棵树的节点数 $V$ 和边数 $E$ 必须满足一个简单的等式——边永远比节点少一条。这保证了图不会乱成一团线球,而是清晰的层级结构。

此外还有一条关于“美观”的性质叫投影性:把所有词从左到右排成一条线,弧画在线上方,如果弧与弧互不交叉,就是投影性的。交叉的弧在工程上更难处理,就像乐高图纸里如果两根线缠在一起,拼装者容易看晕。好在绝大多数语言的日常句子都满足投影性,只有少数疑问句或倒装句会出现交叉。

当你看到一棵完整的依存树时,就等于看到了句子的骨骼——谁是骨架中央的“主梁”,谁是撑起屋檐的“辅柱”,一目了然。这就是机器眼中的句子结构图。

∣E∣=∣V∣−1|E| = |V| - 1
一棵合法的依存树,边数永远比节点数少一个。这就像一棵真正的树:根、干、枝加起来,每根枝条只连着一个父枝条,没有断环。
  1. 节点集合$V$ 是句子中全部词的集合。
    V={w1,w2,…,wn}V = \{w_1, w_2, \dots, w_n\}
  2. 边集合$E$ 是所有依存弧的集合,每条弧连接一个父节点和子节点。
    E={(wj→wi)∣wi∈V, i≠j}E = \{(w_j \rightarrow w_i) \mid w_i \in V, \ i \neq j\}
  3. 树性质边数比节点数少一个,且没有环,所以图是一棵树。
    ∣E∣=∣V∣−1|E| = |V| - 1

构建方法:自动搭建算法

让机器自动搭建依存树,主要有两条路线,对应两种搭乐高的策略。第一种像“照着说明书逐步拼”:从第一个词开始,一边读一边组装,每一步只做一个决定。这就是转移式解析(transition-based parsing),它用一个栈和一个缓冲区维护组装进度,反复执行三类动作——SHIFT(把新词从缓冲区推到栈顶)、LEFT-ARC(让栈顶第二个词依存于栈顶第一个词)、RIGHT-ARC(反向建立依存)。动作做完,树也搭完了。

第二种像“把全部积木摊开在地板上,研究整体布局后才拼”:这就是图式解析(graph-based parsing)。它先枚举所有可能的词对组合,为每一对打分,然后求一个全局最优的“最大生成树”,保证整棵树得分最高。近年主流的实现用神经网络给词对打分,例如基于双仿射注意力(biaffine attention)的 Deep Biaffine Parser,端到端学习词向量和关系分类器,精度大幅提升。

转移式、图式的核心都可以抽象成一个概率模型:在某个解析状态(配置)$c_t$ 下,选择某个动作 $a_t$ 的概率越大,越说明这个动作正确。公式如下:

搭积木这件事,机器可以一步步顺着拼(转移式),也可以全局观想好再拼(图式)。两者各有擅场:转移式速度快,图式全局更稳,现代系统常常混合两者优势。

P(at∣ct)=softmax(W⋅ϕ(ct))P(a_t \mid c_t) = \text{softmax}\left(W \cdot \phi(c_t)\right)
$c_t$ 是此刻的“拼装现场”(栈与缓冲区),$\phi(c_t)$ 是从现场提取的“手感特征”,经过打分后,softmax 把它变成每个动作的采纳概率。
  1. 解析配置$c_t$ 是时间步 $t$ 的解析状态,包括栈、缓冲区和已建的弧。
    ct=(stackt,buffert,arcst)c_t = (\text{stack}_t, \text{buffer}_t, \text{arcs}_t)
  2. 特征提取$\phi(c_t)$ 从配置中抽取有用信息,比如栈顶两个词的词性、依存关系候选。
    ϕ(ct)∈Rd\phi(c_t) \in \mathbb{R}^d
  3. 动作打分权重矩阵 $W$ 把特征向量映射成每个候选动作的得分,得分越高代表越优先。
    score(at)=W⋅ϕ(ct)\text{score}(a_t) = W \cdot \phi(c_t)
  4. 概率归一化softmax 把得分压成和为 1 的概率分布,解析器每次选概率最大的动作。
    P(at∣ct)=exp⁡(score(at))∑a′exp⁡(score(a′))P(a_t \mid c_t) = \frac{\exp(\text{score}(a_t))}{\sum_{a'} \exp(\text{score}(a'))}

经典工具:现成流水线

有了算法还不够,你真去搭乐高时不会从开模做起,而是买套装。NLP 界也把依存解析打包装进了现成“流水线”,开箱即用。学术界最知名的是 Stanford CoreNLP 和 Java 版的 Stanford Parser,英文分析扎实,文档齐全;中文用户则常选哈工大 LTP,分词、词性、依存一条龙,对中文语序优化得很好。

工业界更偏好 Stanza(斯坦福官方 Python 库,支持 70+ 语言,精度高)和 spaCy(推理极快,内存可控,适合线上服务)。选型就像挑乐高套装:收藏党看零件精细度(精度),工程派看拼装速度(延迟),多语言项目则看套装覆盖面(语言支持)。

工具之间的差距可以用标准评测指标衡量,最常用的是 F1 分数,它同时兼顾“找得准”和“找得全”。定义如下:$P$ 是精确率(预测为正确关系的弧中真正正确的比例),$R$ 是召回率(标准答案中真被找到的比例),F1 是二者的调和平均:

在真实项目中,90% 的团队不需要自己训练解析器,而是直接调用这些工具体验“开箱即搭”的爽快感。选对工具,工程就成功了一半。

F1=2×P×RP+R\text{F1} = \frac{2 \times P \times R}{P + R}
F1 把“准”和“全”两个指标拧成一个数,避免只追求其中一个而偏科。就像评价一套乐高说明书,既不能错印太多(低精确率),也不能漏印太多(低召回率)。
  1. 精确率$P$ 表示机器画出的所有依存弧中,正确的弧占多少。
    P=正确预测的关系弧数预测的全部关系弧数P = \frac{\text{正确预测的关系弧数}}{\text{预测的全部关系弧数}}
  2. 召回率$R$ 表示标准答案里的正确弧,机器找回了多少。
    R=正确预测的关系弧数标准答案的全部关系弧数R = \frac{\text{正确预测的关系弧数}}{\text{标准答案的全部关系弧数}}
  3. 调和平均F1 对 $P$ 和 $R$ 取调和平均,数值高说明既不乱找也不漏找。
    F1=2×P×RP+R\text{F1} = \frac{2 \times P \times R}{P + R}

常见应用:搭完有何用

辛辛苦苦搭好乐高城堡,总不能只摆在橱窗里。依存树的最大价值,是作为“语义基础设施”支撑各种 NLP 应用。第一个典型应用是信息抽取。新闻“苹果公司发布新款手机”经依存解析后,核心动词“发布”连接了主语“苹果公司”和宾语“新款手机”,系统顺势抽取出三元组 $(苹果公司, 发布, 新款手机)$,这正是知识图谱需要的原料。

第二个应用是情感分析。评论“这家餐厅的菜品虽然贵,但服务很好”——如果只看关键词,“贵”是负面词,“好”是正面词,机器会犯晕。依存解析却能看清:“贵”修饰的是“菜品”,“好”修饰的是“服务”,两个观点对象分开评价,情感得分自然更准确。机器翻译也依赖它来理顺语序(尤其是日语、韩语等主宾谓结构与英语不同),问答系统则用它理解“苹果公司今年发布了什么”这个问句的重心在“发布”及其实体上。

这些应用都可以抽象成“从关系中抽三元组”:给定头实体、关系、尾实体,输出结构化知识。形式化地写:

城堡盖好了,自然能装人、储物、观景。依存树搭好了,信息抽取、情感分析、机器翻译这些“住户”就能搬进来。没有这棵树,下游任务就只能靠猜。

Triple=(e1,r,e2)\text{Triple} = (e_1, r, e_2)
一个三元组就像乐高套装里的一组可复用部件:$(实体1, 关系, 实体2)$。依存树负责告诉你谁和谁有关、什么关系,剩下的抽取工作就顺水推舟了。
  1. 头实体$e_1$ 通常从依存树的主语位置提取,是关系的“施事者”。
    e1=subj(whead)e_1 = \text{subj}(w_{\text{head}})
  2. 关系$r$ 可取自核心谓词或依存标签,表示实体间的语义联系。
    r=deprel(whead,wdep)r = \text{deprel}(w_{\text{head}}, w_{\text{dep}})
  3. 尾实体$e_2$ 通常从宾语位置提取,是关系的“承受者”。
    e2=obj(wdep)e_2 = \text{obj}(w_{\text{dep}})

日常局限:乐高也怕卡壳

乐高再好玩,遇到几千块零件的巨型套装也会拼到怀疑人生。依存解析同样有怕的东西:长难句是头号杀手。一个句子从句套从句、定语链超过三层时,歧义数量爆炸式增长,即使是 SOTA 模型也会看走眼。比如“他看见了那个拿着望远镜的朋友”——“拿着望远镜”修饰的是“他”还是“朋友”?人类都得分想一下,机器更是容易站错队。

口语和不规范文本也让人头疼。聊天记录里的“哈哈哈笑死我了”、B 站弹幕“这波啊这波是白给”,省略、倒装、错别字层出不穷,依存解析器面对这些“自由拼搭”的乐高零件常常直接懵圈。此外,歧义消解是核心难题,尤其是介词短语挂靠(“在桌子上的猫” vs “看在桌子上的猫”),依存树只能给一种答案,选错就全错。

工程上还要考虑复杂度权衡。转移式解析速度快,时间复杂度低,适合长文本流式处理;图式解析要枚举词对打分,复杂度更高,但全局效果更好。二者的复杂度差异如下:

所以说,依存解析这位“拼装大师”也有脾气:句子太绕、文本太随意、延迟要求太苛刻时,它照样会手忙脚乱。理解这些局限,比盲目相信工具输出更重要。

Ttrans=O(n),Tgraph=O(n2)T_{\text{trans}} = O(n), \qquad T_{\text{graph}} = O(n^2)
$n$ 是句子长度。转移式花费时间随句子线性增长(每词处理固定次数),图式则是平方级增长(要评估所有词对),句子稍长后者就会明显变慢。
  1. 转移式复杂度每个词入栈、出栈操作次数固定,整体耗时随句子长度线性增长。
    Ttrans=O(n)T_{\text{trans}} = O(n)
  2. 图式复杂度模型要为约 $n^2$ 个候选词对依次打分,句子变长时开销迅速变大。
    Tgraph=O(n2)T_{\text{graph}} = O(n^2)
  3. 工程选择在长文档或实时场景中,常选转移式换取速度;离线或追求极限精度时用图式。
    O(n)<O(n2)(n→∞)O(n) < O(n^2) \quad (n \to \infty)

AI 应用场景

新闻事件信息抽取

阶段:文本预处理 + 结构化信息提取

解决的问题:新闻稿件是自由文本,传统基于正则的规则引擎只能匹配固定模板,遇到“苹果公司于昨日正式发布新款手机”这种千变万化的表达就失效。AI 用依存解析找出核心动词“发布”的主语和宾语,自动抽取三元组。

具体案例:某金融舆情系统每天处理 10 万条财经新闻,用 LTP 对每句话做依存解析,提取“公司—动作—对象”三元组,再汇聚成知识图谱。原本人工整理需要 3 小时的资讯摘要,现在秒级完成,召回率还提升了 20%。

电商评论情感分析

阶段:特征工程 + 情感分类

解决的问题:简单词袋模型分不清“手机拍照好但电池不耐用”中“好”和“不耐用”分别描述哪个部件。依存解析让模型先明确观点对象(拍照/电池)和观点词(好/不耐用)的修饰关系,再做细粒度情感判断。

具体案例:某电商平台用 spaCy 对商品评论做依存解析,分解出“屏幕-清晰”、“续航-差”等属性级情感对,自动生成每个商品维度的评分雷达图。用户点开详情页,直接看到“续航 2.1 分(1553 条用户反馈)”。

智能客服问句解析

阶段:用户意图理解 + 槽位填充

解决的问题:“我想查一下上个月的账单明细”和“上个月账单明细给我看看”,句式不同但意图相同。依存解析把问句的中心动作和宾语关系捋直,让意图分类器从“句式相似”升级为“语义相似”。

具体案例:某银行智能客服接入依存解析后,把“如何修改预留手机号?”解析为“[修改] 对象:[手机号]”,再映射到知识库中的“个人信息变更”流程。上线后问句识别准确率从 78% 提升到 91%,转人工率下降 35%。

Python 演示

python67 行
class ArcStandardParser:    """简化版 arc-standard 转移式依存解析器演示"""     def __init__(self, words):        self.words = words        self.stack = []        self.buffer = list(range(len(words)))        self.heads = [None] * len(words)  # heads[i] = (head_idx, rel)     def shift(self):        self.stack.append(self.buffer.pop(0))     def left_arc(self, rel):        head = self.stack[-1]        dep = self.stack.pop(-2)        self.heads[dep] = (head, rel)     def right_arc(self, rel):        head = self.stack[-2]        dep = self.stack.pop(-1)        self.heads[dep] = (head, rel)     def reduce(self):        self.stack.pop()     def parse(self, actions):        for action in actions:            if action[0] == 'SHIFT':                self.shift()            elif action[0] == 'LEFT':                self.left_arc(action[1])            elif action[0] == 'RIGHT':                self.right_arc(action[1])            elif action[0] == 'REDUCE':                self.reduce()            self.show_state(action)     def show_state(self, action):        stack_str = '/'.join(self.words[i] for i in self.stack) if self.stack else '[]'        buf_str = '/'.join(self.words[i] for i in self.buffer) if self.buffer else '[]'        print('%-8s 栈: %-12s 缓冲区: %-12s' % (action[0], stack_str, buf_str))     def show_tree(self):        print()        for i, h in enumerate(self.heads):            if h is not None:                print('%s <- %s (%s)' % (self.words[i], self.words[h[0]], h[1]))            else:                print('%s 是根节点(ROOT)' % self.words[i])  def main():    words = ['小猫', '吃', '鱼']    parser = ArcStandardParser(words)    actions = [        ('SHIFT',),        ('SHIFT',),        ('LEFT', '主谓'),        ('SHIFT',),        ('RIGHT', '动宾'),    ]    parser.parse(actions)    parser.show_tree()  if __name__ == '__main__':    main()
目的:演示 arc-standard 转移式依存解析器的核心循环——通过 SHIFT、LEFT-ARC、RIGHT-ARC 三类动作,从左到右扫描句子并逐步搭建依存树。
  1. self.heads = [None] * len(words)用列表记录每个词的支配词和关系,None 表示该词是根节点。
  2. def shift(self)把缓冲区首词推进栈,对应“从零件堆拿一块积木放到搭建台上”。
  3. def left_arc(self, rel)栈顶第二个词依存于栈顶词,并弹出它,对应“把下面那块积木卡到上面那块”。
  4. def right_arc(self, rel)反向建立依存:栈顶词依存于栈顶第二个词,并弹出栈顶词。
  5. parser.parse(actions)按预定义动作序列执行全部步骤,打印每一步的栈和缓冲区状态。
  6. parser.show_tree()输出最终的依存关系表,直观看到“谁支配谁”。

常见误区

误区我一直以为分词、词性标注、依存解析是一回事,做了分词和词性标注就算完成文本预处理了,不需要再管什么依存关系。

正解分词只是把句子切成积木块,词性标注是在积木上贴“颜色标签”(名词、动词),而依存解析是确定积木之间的卡扣关系——谁卡在谁身上、以什么方式卡。三者是层层递进的三道工序,用途完全不同:情感分析需要依存关系来定位“观点词修饰谁”,仅靠词性做不到。

为何常见:因为很多 NLP 工具链默认一起输出分词、词性、依存结果,初学者容易把三个输出混为一谈,误以为机器“一次性”完成了所有句法分析。

误区我上学时学过“主谓宾定状补”,觉得依存树就是把它换个画法,本质上跟句子的语法树(短语结构树)一样。

正解两者观察角度完全不同。短语结构树是把句子切成一层层的“盒子”(句子内有名词短语、动词短语),强调组合关系;依存树则跳过中间的盒子,直接画一条从核心动词到每个词的弧,强调词与词之间的支配依赖。同一个句子,两种树画出来形态差异很大,实际应用中也各有优劣。

为何常见:因为中小学语文的“句子成分分析”也是画箭头找主干,第一眼看依存树觉得“这跟语文老师教的主谓宾划法差不多啊”,于是想当然套用旧知识。

误区我用 spaCy 或 LTP 对句子做解析,拿到结果就直接存库了,认为这些大厂工具输出肯定没错。

正解依存解析器的准确率一般不会 100% 正确,长难句、口语化文本上错误率会明显上升。正确做法是把解析结果当作“高置信候选”,在关键业务中增加校验环节,例如用规则过滤明显错误的弧、对分类置信度低的句子人工复核。

为何常见:工业级工具封装得太好,用户只看到漂亮的依存树图,看不到背后的概率分布和误判风险,容易产生“机器全对”的错觉。

误区中文语序灵活、没有形态变化,跟英文完全是两套体系,所以英文的依存解析方法在中文上没法用。

正解中文确实有自己的难点(如分词歧义、缺少形态标记),但依存关系的抽象框架是跨语言通用的——主语、宾语、定语这些语义角色两种语言都有。主流工具(Stanza、LTP)都基于通用的依存标注体系,只是内部模型用不同语言的树库分别训练。方法可以迁移,细节要调参。

为何常见:因为学习任何 NLP 概念时都先碰到语言差异的宣传,再加上中文分词这一独有前置步骤,容易放大“中文特殊”的直觉。

面试题

Q1. 依存解析的核心输出是什么?

单选题 · easy

  • A.分词结果列表
  • B.词性标注标签
  • C.依存弧及其关系标签← 正确答案
  • D.命名实体识别结果

答案:C。依存解析的目标是为每对存在主从关系的词画一条带标签的有向弧,而不是单纯分词或标词性。就像搭乐高,核心输出不是“积木清单”而是“卡扣连接图”。D 选项是命名实体识别,属于另一个任务。

Q2. 一棵包含 n 个词的合法依存树有几条边?

单选题 · easy

  • A.n 条
  • B.n - 1 条← 正确答案
  • C.n + 1 条
  • D.2n 条

答案:B。树结构要求边数比节点数少一个,即 n 个词对应 n-1 条依存弧。这就像一棵真树,n 块积木用 n-1 个卡扣连接就能串成完整骨架,多一条就会成环,少一条就断开了。

Q3. 在 UD 标注体系中,“小猫吃鱼”里“小猫”和“吃”的关系标签是?

单选题 · easy

  • A.obj
  • B.nsubj← 正确答案
  • C.det
  • D.amod

答案:B。nsubj 表示名词性主语,即“小猫”是“吃”的主语;obj 是宾语,对应“鱼”;det 是限定词,amod 是形容词修饰语。主语是施事者,宾语的标签是 obj,别记反方向。

Q4. arc-standard 转移式解析器的核心动作不包括哪一项?

单选题 · mid

  • A.SHIFT
  • B.LEFT-ARC
  • C.RIGHT-ARC
  • D.SPLIT← 正确答案

答案:D。arc-standard 的三大核心动作是 SHIFT(入栈)、LEFT-ARC(左归约)、RIGHT-ARC(右归约),没有 SPLIT 这个动作。SPLIT 是某些序列分割任务的术语,不属于转移式依存解析的动作集。

Q5. 以下哪些是依存解析的典型应用场景?

多选题 · mid

  • A.信息抽取← 正确答案
  • B.情感分析← 正确答案
  • C.机器翻译← 正确答案
  • D.图像分类

答案:ABC。依存树为信息抽取提供三元组来源,为情感分析定位观点对象,为机器翻译提供语序调整依据。图像分类处理的是像素而非文本,不需要词间依存关系。

Q6. 图式依存解析的全局目标是找到?

单选题 · mid

  • A.最大生成树← 正确答案
  • B.最小生成树
  • C.最长公共子序列
  • D.最短路径树

答案:A。图式解析先为所有候选词对打分,再在图上求一棵总权重最大的生成树(Maximum Spanning Tree),确保所有弧得分之和最高。最小生成树是找权重最小的连接,方向正好相反。

Q7. F1 分数是由哪两个指标调和平均得到的?

单选题 · mid

  • A.准确率和召回率
  • B.精确率和召回率← 正确答案
  • C.精确率和准确率
  • D.召回率和损失值

答案:B。F1 = 2PR / (P + R),其中 P 是精确率(预测的弧里有多少正确),R 是召回率(正确的弧里找回多少)。准确率不是“调和平均的组成项”,别把准确率与精确率混为一谈。

Q8. 依存解析在中文场景中常见的挑战有哪些?

多选题 · hard

  • A.长难句歧义剧增← 正确答案
  • B.口语文本省略严重← 正确答案
  • C.介词短语挂靠歧义← 正确答案
  • D.词表大小影响分词

答案:ABC。长难句、口语省略和介词短语挂靠都会让依存关系难以判断。D 选项“词表大小”主要影响分词阶段,不是依存解析独有难题,且现代子词分词已基本缓解词表瓶颈。

Q9. 在“小猫吃鱼”这棵依存树中,根节点是哪个词?

单选题 · hard

  • A.小猫这个词
  • B.吃这个词← 正确答案
  • C.鱼这个词
  • D.无根节点

答案:B。依存树的根节点通常是句子的核心谓语动词。“吃”支配“小猫”(nsubj)和“鱼”(obj),是整棵树的最高支配者。主语和宾语都依附于它,因此根是“吃”,不是“小猫”或“鱼”。

Q10. 关于依存树的投影性,下列说法正确的有?

多选题 · extreme

  • A.非投影树的弧线会交叉← 正确答案
  • B.投影性要求所有弧互不交叉← 正确答案
  • C.所有语言都严格满足投影性
  • D.工程上可重排序处理非投影← 正确答案

答案:ABD。把词按顺序排成直线后,投影性要求弧线互不交叉;非投影树必然出现交叉弧,因此 A、B 正确。C 错误——德语、俄语等语言的疑问句和倒装句会出现非投影结构。D 正确,很多解析器会先做重排序或特殊处理来消化非投影现象。