spaCy 如何用 DependencyMatcher 按依存句法结构匹配模式? 📅 发布时间:2026/9/12 17:44:24 👁 浏览次数: spaCy 如何用 DependencyMatcher 按依存句法结构匹配模式【免费下载链接】spaCy Industrial-strength Natural Language Processing (NLP) in Python项目地址: https://gitcode.com/GitHub_Trending/sp/spaCyMatcher的 token 模式按文本中 token 的出现顺序排列只能描述相邻 token 的序列。当你需要匹配的是句法关系——“哪个名词是某动词的主语”“宾语带有哪种修饰语”——就需要在依存句法树上做匹配而不是在 token 序列上。spaCy v3 的DependencyMatcher用 Semgrex 算子来表达这类结构关系你指定一个锚点 token再通过关系算子把其他 token 一个个挂到锚点上最终得到一组匹配到的 token 索引。本文按 DependencyMatcher API 文档 和 Rule-based matching 使用指南 中的 “founded” 示例走一遍从设计模式到验证结果的完整流程。前提需要一个带 parser 的模型DependencyMatcher的文档明确要求一个预训练的DependencyParser或其他会设置Token.dep和Token.head属性的组件依赖标签不存在的模型如spacy.blank无法支撑匹配。使用指南中标注该功能适用于 spaCy v3。文档示例使用的模型是en_core_web_sm下载并加载方式见 模型文档$ python -m spacy download en_core_web_smimport spacy from spacy.matcher import DependencyMatcher nlp spacy.load(en_core_web_sm) matcher DependencyMatcher(nlp.vocab)注意vocab必须与 matcher 将处理的文档共享nlp.vocab这是 API 文档对DependencyMatcher(vocab)的参数要求。模式的结构锚点 token 加关系字典一个模式是字典列表每个字典描述一个待匹配的 token 及其与模式中已有 token 的关系。第一个字典定义锚点 token只使用RIGHT_ID和RIGHT_ATTRS之后每个字典使用下表中的键键含义LEFT_ID关系中左侧节点的名字必须已在此前的字典中定义过REL_OP描述两个节点关系的算子RIGHT_ID右侧节点的唯一名字RIGHT_ATTRS右侧节点要匹配的 token 属性格式与Matcher的 token 模式相同每个新 token 都通过REL_OP链接到一个已有的LEFT_ID并取一个新的RIGHT_ID。文档特别提醒字典的顺序很重要——一个 token 名字必须先作为RIGHT_ID定义才能在后续字典中作为LEFT_ID引用。关系算子支持以下算子大部分直接来自 Semgrex算子含义A BA是B的直接 dependentA BA是B的直接 headA BA是到B的 dep → head 链上的 dependentA BA是到B的 head → dep 链上的 headA . BA紧邻在B之前A.i B.i - 1且在同一依存树内A .* BA在B之前A.i B.i且在同一依存树内A ; BA紧邻在B之后A.i B.i 1且在同一依存树内A ;* BA在B之后A.i B.i且在同一依存树内A $ BB是A的右侧紧邻兄弟同一 parentA.i B.i - 1A $- BB是A的左侧紧邻兄弟同一 parentA.i B.i 1A $ BB是A的右侧兄弟同一 parentA.i B.iA $-- BB是A的左侧兄弟同一 parentA.i B.iA B3.5.1 新增B是A的右侧紧邻子节点A.i B.i - 1A - B3.5.1 新增B是A的左侧紧邻子节点A.i B.i 1A BB是A的右侧子节点A.i B.iA -- BB是A的左侧子节点A.i B.iA B3.5.1 新增B是A的右侧紧邻 parentA.i B.i - 1A - B3.5.1 新增B是A的左侧紧邻 parentA.i B.i 1A BB是A的右侧 parentA.i B.iA -- BB是A的左侧 parentA.i B.i示例匹配“谁创立了哪种公司”使用指南中的场景是找出 “Smith founded a healthcare company in 2005.” 这类描述“谁创立了什么公司”的句子。目标句子中的依存关系是创始人是founded的主语nsubj公司名是founded的直接宾语dobj公司类型可能是形容词修饰amod或复合修饰compound。设计模式前先看一下实际句子的依存解析。指南中给出的查看方式是import spacy from spacy import displacy nlp spacy.load(en_core_web_sm) doc nlp(Smith founded a healthcare company) displacy.serve(doc)displacy.serve会在浏览器中渲染Doc及其依存结构和词性标注你可以据此确认要用的 dep 标签是否与解析结果一致。第 1 步先只匹配锚点 token选founded作为锚点它是依存树的根且让所有关系算子都从 head 指向 child 时模式更好写。最小模式只命名一个 tokenimport spacy from spacy.matcher import DependencyMatcher nlp spacy.load(en_core_web_sm) matcher DependencyMatcher(nlp.vocab) pattern [ { RIGHT_ID: anchor_founded, # unique name RIGHT_ATTRS: {ORTH: founded} # token pattern for founded } ] matcher.add(FOUNDED, [pattern]) doc nlp(Smith founded two companies.) matches matcher(doc) print(matches) # [(4851363122962674176, [1])]运行后输出形如[(4851363122962674176, [1])]文档示例结果第一个元素是模式 ID第二个列表是匹配到的 token 索引[1]对应founded。第 2 步挂上主语和宾语有了命名的锚点anchor_founded后用把主语nsubj和宾语dobj作为founded的直接 dependent 挂进来pattern [ { RIGHT_ID: anchor_founded, RIGHT_ATTRS: {ORTH: founded} }, { LEFT_ID: anchor_founded, REL_OP: , RIGHT_ID: founded_subject, RIGHT_ATTRS: {DEP: nsubj}, }, { LEFT_ID: anchor_founded, REL_OP: , RIGHT_ID: founded_object, RIGHT_ATTRS: {DEP: dobj}, } ]第 3 步给宾语加修饰语条件最后要求宾语founded_object带一个amod或compound关系的修饰 token。RIGHT_ATTRS支持Matcher的富比较语法用{IN: [...]}表达“dep 标签属于某列表”pattern [ # ... { LEFT_ID: founded_object, REL_OP: , RIGHT_ID: founded_object_modifier, RIGHT_ATTRS: {DEP: {IN: [amod, compound]}}, } ]运行完整模式并核对结果完整模式与执行代码import spacy from spacy.matcher import DependencyMatcher nlp spacy.load(en_core_web_sm) matcher DependencyMatcher(nlp.vocab) pattern [ { RIGHT_ID: anchor_founded, RIGHT_ATTRS: {ORTH: founded} }, { LEFT_ID: anchor_founded, REL_OP: , RIGHT_ID: founded_subject, RIGHT_ATTRS: {DEP: nsubj}, }, { LEFT_ID: anchor_founded, REL_OP: , RIGHT_ID: founded_object, RIGHT_ATTRS: {DEP: dobj}, }, { LEFT_ID: founded_object, REL_OP: , RIGHT_ID: founded_object_modifier, RIGHT_ATTRS: {DEP: {IN: [amod, compound]}}, } ] matcher.add(FOUNDED, [pattern]) doc nlp(Lee, an experienced CEO, has founded two AI startups.) matches matcher(doc) print(matches) # [(4851363122962674176, [6, 0, 10, 9])] # Each token_id corresponds to one pattern dict match_id, token_ids matches[0] for i in range(len(token_ids)): print(pattern[i][RIGHT_ID] :, doc[token_ids[i]].text)对输入句 “Lee, an experienced CEO, has founded two AI startups.”文档示例输出为[(4851363122962674176, [6, 0, 10, 9])]。按 API 文档对__call__的说明返回列表由(match_id, token_ids)组成token_ids中每个 token 索引的位置与模式字典的顺序一一对应——[6, 0, 10, 9]依次对应anchor_foundedfounded、founded_subjectLee、founded_objectstartups、founded_object_modifierAI。上面的循环把每个RIGHT_ID打印成实际 token就是这个对照关系的验证方式。其他可用的接口与调试手段validate参数DependencyMatcher(nlp.vocab)支持 keyword-only 参数validate开启后所有添加的模式都会被校验适合开发阶段发现写错的模式。on_match回调matcher.add(match_id, patterns, on_matchcallback)的回调接收matcher、doc、i、matches四个参数可以对每次匹配执行自定义逻辑。规则管理len(matcher)返回已添加的规则数等于 ID 数不是模式数matcher.get(key)返回(on_match, patterns)元组matcher.remove(key)删除规则ID 不存在时抛KeyError对已存在的 ID 再次调用add会扩展模式列表而on_match会被覆盖。性能限制文档给出了一条明确的速度警告当 token 模式可能匹配句中很多 token或关系算子允许在依存树中走较长路径如、、.*、;*时DependencyMatcher可能很慢。文档给出的改进方向是让 token 模式和算子尽可能具体——例如能写就不要写用带依赖标签等属性的模式代替能匹配任意 token 的{}。另注意算子、-、、-是 spaCy 3.5.1 新增的更早版本不可用它们也不属于 Semgrex 原生算子。完整的模式设计说明见 DependencyMatcher 使用指南章节接口参数细节见 DependencyMatcher API。【免费下载链接】spaCy Industrial-strength Natural Language Processing (NLP) in Python项目地址: https://gitcode.com/GitHub_Trending/sp/spaCy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考