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

如何将spaCy偏移格式转为GoldDoc以CLI训练带自定义LABEL的NER模型

如何将spaCy偏移训练格式转换为Gold格式以用于CLI训练

我完全懂你的需求——你已经把NER数据转成了spaCy的偏移格式,现在想切换到更灵活的CLI训练方式,但卡在了偏移格式转Gold格式这一步,而且不想依赖现成的nlp实例,毕竟要从零构建带自定义标签(PERSON、PHONE、ADDRESS)的模型对吧?下面给你两种可行的解决方案:

方案一:用空白nlp实例生成BILUO标签(推荐)

你提到的biluo_tags_from_offsets确实需要一个Doc对象,但咱们不需要用预训练的nlp模型,只需要初始化一个空白的nlp实例,并手动添加你的自定义标签就行,这样既不会有预训练模型的干扰,又能利用spaCy内置的工具函数完成转换。

具体步骤代码如下:

import spacy
from spacy.training import biluo_tags_from_offsets

# 1. 初始化空白的nlp实例(根据你的文本语言指定,比如法语fr,或者用xx表示多语言)
nlp = spacy.blank("fr")

# 2. 添加NER组件,并注册你的自定义标签
ner = nlp.add_pipe("ner")
for label in ["PERSON", "PHONE", "ADDRESS"]:
    ner.add_label(label)

# 3. 处理你的偏移格式数据
offset_data = [
    [
        "Bonjour\r\n\r\n\r\n\r\ncordialement, Thomas\r\n\r\n tel 0102030405",
        {"entities": [[70,79,"PHONE"],[56,61,"PERSON"]]}
    ]
]

# 4. 转换为Gold格式(BILUO标签序列)
gold_data = []
for text, annotations in offset_data:
    doc = nlp(text)
    # 提取实体偏移的三元组格式(start, end, label)
    offsets = [(start, end, label) for start, end, label in annotations["entities"]]
    biluo_tags = biluo_tags_from_offsets(doc, offsets)
    gold_data.append({"text": text, "tags": biluo_tags})

# 5. 保存为JSONL格式(spaCy CLI训练要求的输入格式)
import json
with open("train_gold.jsonl", "w", encoding="utf-8") as f:
    for item in gold_data:
        json.dump(item, f, ensure_ascii=False)
        f.write("\n")

方案二:手动实现偏移到BILUO标签的转换

如果不想依赖spaCy的nlp实例,也可以手动写逻辑生成BILUO标签。核心思路是:

  • 先初始化一个全为O的标签列表,长度和文本的token数一致
  • 遍历每个实体偏移,找到对应的token位置,然后根据实体的token个数标记B(开头)、I(中间)、L(结尾)、U(单个token)标签

不过这种方法需要保证tokenization逻辑和spaCy的tokenizer完全一致,否则CLI训练时会出现标签对齐问题,所以不如方案一省心,这里给你一个简化的示例思路:

def offsets_to_biluo(text, entities, tokenizer):
    tokens = tokenizer(text)
    tags = ["O"] * len(tokens)
    # 记录每个token的起始和结束位置
    token_start_end = [(token.idx, token.idx + len(token)) for token in tokens]
    
    for ent_start, ent_end, ent_label in entities:
        # 找到实体覆盖的所有token索引
        token_indices = []
        for i, (tok_start, tok_end) in enumerate(token_start_end):
            # 判断token和实体是否有重叠
            if not (ent_end <= tok_start or ent_start >= tok_end):
                token_indices.append(i)
        
        if not token_indices:
            continue
        
        # 标记BILUO标签
        if len(token_indices) == 1:
            tags[token_indices[0]] = f"U-{ent_label}"
        else:
            tags[token_indices[0]] = f"B-{ent_label}"
            for i in token_indices[1:-1]:
                tags[i] = f"I-{ent_label}"
            tags[token_indices[-1]] = f"L-{ent_label}"
    return tags

# 使用空白nlp的tokenizer保证和CLI训练时的tokenization一致
nlp = spacy.blank("fr")
tokenizer = nlp.tokenizer
# 调用函数生成标签

CLI训练的额外注意事项

转换完Gold格式后,你需要在spaCy的训练配置文件(config.cfg)里指定你的自定义标签,比如在[components.ner]部分添加:

[components.ner]
factory = "ner"
labels = ["PERSON", "PHONE", "ADDRESS"]

这样CLI训练时就能正确识别你的自定义标签了。

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

相关产品推荐
方舟 Agent Plan

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

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