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

使用自定义suggester时SpanCategorizer训练数据格式及零损失问题

spaCy自定义主张抽取Pipeline问题解答

问题1:SpanCategorizer训练数据的span起止用字符偏移还是token索引?

必须使用token索引。

spaCy的Span对象基于文档的token序列创建,Span(doc, start, end, label)中的start和end是token的索引(左闭右开区间,比如(1,2)对应文档第2个token,索引从0开始)。字符偏移仅用于doc.char_span(start_char, end_char)方法生成Span,但SpanCategorizer训练时,标注数据的span必须以token索引形式提供,因为模型内部基于token级特征学习。

你的训练数据示例中使用(1, 2, "SOURCE")的token索引格式是正确的。

问题2:训练循环返回0损失的原因及修复

训练损失为0的核心问题是训练数据未正确传递给模型的gold标注,同时存在其他配置疏漏,具体修复如下:

1. 修复Example构建逻辑

你的示例构建代码中,Example.from_dict(doc, {})传入空字典作为gold数据,导致模型没有标注可学习,损失始终为0。

修正代码:

examples = []
for text, annots in training_data: 
    doc = nlp.make_doc(text) 
    # 直接将标注数据传入Example作为gold标准
    example = Example.from_dict(doc, annots)
    examples.append(example)

若需手动构建Span后生成Example,也要确保gold标注正确传入:

examples = []
for text, annots in training_data: 
    doc = nlp.make_doc(text) 
    spans_to_add = []
    for span in annots["spans"]["sc"]: 
        start, end, label = span
        new_span = Span(doc, start, end, label) 
        spans_to_add.append(new_span)
    doc.spans["sc"] = spans_to_add 
    # 传入完整标注数据而非空字典
    examples.append(Example.from_dict(doc, annots))

2. 修正训练数据格式

你的training_data存在语法错误,正确格式应为包含(text, annots)元组的列表:

training_data = [
    (
        "The report states that AI risks are increasing significantly.",
        {
            "spans": {
                "sc": [
                    (1, 2, "SOURCE"),
                    (2, 3, "CLAIM_VERB"),
                    (4, 8, "CLAIM_CONTENTS"),
                    (8, 9, "CLAIM_MOD"),
                ]
            }
        }
    )
]

3. 确保Suggester生成候选包含gold span

SpanCategorizer仅对suggester返回的候选span分类,若gold span不在候选列表中,模型无法学习对应标签,也会导致损失异常。需检查自定义suggester逻辑:

  • 确保训练数据中的每个gold span,都能通过依存解析逻辑生成对应的(start, end)候选区间
  • 比如验证gold span(4,8,"CLAIM_CONTENTS")是否能被suggester正确识别并加入候选

4. 规范训练循环写法

确保已正确获取spancat组件并完成配置:

# 加载预训练模型并添加spancat组件
nlp = spacy.load("en_core_web_sm")
config = {
    "threshold": 0.5,
    "spans_key": "sc",  # 与训练数据中的spans键对应
    "suggester": {"@misc": "claim_suggester.v1"},
    "labels": ["SOURCE", "CLAIM_VERB", "CLAIM_CONTENTS", "CLAIM_MOD"]
}
nlp.add_pipe("spancat", config=config)

# 训练循环
spancat = nlp.get_pipe("spancat")
optimizer = nlp.initialize()
   
epochs = 30
for itn in range(epochs): 
    random.shuffle(examples)
    losses = {}
    batches = spacy.util.minibatch(examples, size=4)
    for batch in batches: 
        spancat.update(batch, drop=0.2, losses=losses, sgd=optimizer)
    print(f"Iteration: {itn + 1}, Losses: {losses}")
print(f"Number of examples processed: {len(training_data)}")

内容的提问来源于stack exchange,提问作者muelikath_8

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 05:14:52