You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过递归遍历句法树提取不定长度的句子主语?

提取依存句法中的完整主语(含多级依存项)

看起来你已经摸到了门道,只是还缺一个递归/迭代遍历所有层级依存项的逻辑——毕竟主语可能是一个嵌套的名词短语,比如"My mom"里"My"依存于"mom","mom"又依存于核心动词,得把这些层级都捞出来才行。

我来给你梳理一个通用的思路,再附上可运行的Python代码:


核心思路

要搞定这个问题,咱们得分四步走:

  • 定位核心动词:先找到依存索引为-1的词(句子核心),记它在数组里的索引为root_idx
  • 找主语中心词:筛选出所有直接依存于root_idx的名词类(NOUN/PROPN等)词汇,这些是主语的核心
  • 递归收集所有依存项:对每个主语中心词,遍历整个数组,把所有直接/间接依存于它的词都找出来(比如"My"依存于"mom",就得把"My"也纳入)
  • 按原句顺序拼接:把收集到的所有词按它们在原句子中的索引排序,再组合成完整主语

完整代码示例

假设你用的是pymorphy2做形态分析(从你的代码里的morph.parse推测),代码如下:

from pymorphy2 import MorphAnalyzer

morph = MorphAnalyzer()

def extract_subject(values):
    # 1. 找到核心动词的索引
    root_idx = None
    for idx, (word, dep_idx) in enumerate(values):
        if dep_idx == -1:
            root_idx = idx
            break
    if root_idx is None:
        return ""
    
    # 2. 找到所有直接依存于核心动词的名词类词汇(主语中心词候选)
    subject_heads = []
    for idx, (word, dep_idx) in enumerate(values):
        if dep_idx == root_idx:
            # 用形态分析判断是否是名词类
            parsed = morph.parse(word)[0]
            if parsed.tag.POS in ['NOUN', 'PROPN', 'PRON']:  # 覆盖名词、专有名词、代词
                subject_heads.append(idx)
    
    # 3. 迭代收集所有依存于主语中心词的词(含次级依存)
    subject_indices = set(subject_heads)
    # 循环迭代,直到没有新的依存项加入
    changed = True
    while changed:
        changed = False
        for idx, (word, dep_idx) in enumerate(values):
            # 如果当前词的依存索引在已收集的主语索引里,且自身还没被加入
            if dep_idx in subject_indices and idx not in subject_indices:
                # 筛选修饰主语的词类(限定词、形容词、名词等)
                parsed = morph.parse(word)[0]
                if parsed.tag.POS in ['ADJ', 'DET', 'NOUN', 'PROPN', 'PRON']:
                    subject_indices.add(idx)
                    changed = True
    
    # 4. 按原句顺序排序,提取词汇并拼接
    sorted_indices = sorted(subject_indices)
    subject_words = [values[idx][0] for idx in sorted_indices]
    return ' '.join(subject_words)

# 测试你的示例
values = [('My', 1), ('mom', 2), ('wants', -1), ('to', 2), ('cook', 3)]
print(extract_subject(values))  # 输出: My mom

代码解释

  • 核心动词定位:遍历数组找到dep_idx=-1的元素,这是句子的核心谓语
  • 主语中心词筛选:找直接依附于核心动词的名词类词汇,这些是主语的核心部分
  • 迭代收集依存项:用循环不断查找所有依附于已收集主语元素的词,直到没有新的词加入——这就覆盖了所有次级依存(比如"My"依附于"mom"的情况)
  • 顺序拼接:按原句的索引排序,保证输出的主语和原句语序一致

扩展优化

如果你的依存关系数据里有依存关系类型(比如nsubj、det等),可以直接用类型筛选,比POS标签更准确:比如找dep_rel='nsubj'的词作为主语中心,再找dep_rel='det'或dep_rel='amod'的修饰词,这样能更精准地提取主语。

内容的提问来源于stack exchange,提问作者Евгения Рубанова

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:10:55