如何使用spacy-annotator生成的annotations列数据训练spacy模型
你直接导出CSV再读取的操作会将annotations列原本的Python结构化数据转为字符串,无法被spaCy识别,按以下步骤处理即可:
步骤1:提取结构化标注数据
优先直接从原始带标注的TRAINED_DATA中提取数据,避免CSV转义导致的格式异常:
import pandas as pd import ast import spacy from spacy.tokens import DocBin from tqdm import tqdm TRAIN_DATA = [] # 遍历原始标注DataFrame for idx, row in TRAINED_DATA.iterrows(): # 替换为你自己存储标注原文的列名 text = row["text"] annotations = row["annotations"] # 如果之前已经把标注存成了CSV读出来是字符串,加下面这行转成字典 # annotations = ast.literal_eval(annotations) # 过滤重叠实体,spaCy不支持训练重叠实体 valid_ents = [] for start, end, label in annotations.get("entities", []): overlap = False for s, e, l in valid_ents: if not (end <= s or start >= e): overlap = True break if not overlap: valid_ents.append((start, end, label)) TRAIN_DATA.append((text, {"entities": valid_ents}))
步骤2:转换为spaCy标准训练格式
spaCy v3及以上版本要求使用.spacy后缀的二进制训练文件,转换代码如下:
# 加载对应语言的空白模型,中文标注替换为"zh" nlp = spacy.blank("en") doc_bin = DocBin() for text, annot in tqdm(TRAIN_DATA): doc = nlp.make_doc(text) ents = [] for start, end, label in annot["entities"]: # 校验标注偏移量是否和文本匹配 span = doc.char_span(start, end, label=label) if span is None: print(f"跳过不匹配实体:{text[start:end]},位置{start}-{end}") else: ents.append(span) doc.ents = ents doc_bin.add(doc) # 保存训练文件,建议提前按8:2拆分训练集和验证集,分别存储 doc_bin.to_disk("./train.spacy") # 验证集保存为 doc_bin.to_disk("./dev.spacy")
步骤3:启动模型训练
生成对应任务(如命名实体识别NER)的spaCy训练配置文件后,执行以下命令启动训练:
python -m spacy train config.cfg --output ./model_output --paths.train ./train.spacy --paths.dev ./dev.spacy
注意事项
- 标注过程中尽量避免实体重叠,重叠实体无法被spaCy的默认NER组件训练
- 中文训练时需要确保加载的是中文空白模型
spacy.blank("zh") - 如果必须用CSV存储标注结果,需要同时保存原文列和标注列,读取时用
ast.literal_eval把字符串格式的标注转回字典结构
内容的提问来源于stack exchange,提问作者jm_1788
相关产品推荐
相关产品推荐

