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

如何用spaCy和Python提取带B/I/O标记的b-per类NER标签?

问题描述

查阅spaCy文档后尝试用span的labels_属性提取NER标签,但实际返回的是POS标签(如NOUN、DET)而非NER标签。需要生成BIO格式的标记:

  • NER span的第一个token标记为B-<NER类型>(如B-per代表人物实体开头)
  • NER span的后续token标记为I-<NER类型>
  • 非NER token标记为O

目前使用的代码如下,但ent.label_返回POS标签:

for idx, doc in enumerate(train_docs):
    for ent in doc.ents:
        ner_structured_docs.append([idx, ent.text,ent.label_])
解决方案

1. 修正模型加载问题

spaCy中doc.ents里的ent.label_本身就是NER标签,返回POS标签的核心原因是你加载的模型没有包含NER组件,或是使用了空白模型/仅加载词性标注组件的模型。

解决方式:使用带有NER功能的预训练模型,比如英文的en_core_web_sm、中文的zh_core_web_sm,加载示例:

import spacy
nlp = spacy.load("en_core_web_sm")  # 替换为对应语言的预训练模型
# 确保train_docs是经过该nlp处理后的Doc对象
train_docs = list(nlp.pipe(your_raw_texts))

如果是自定义训练的模型,需确认训练时包含NER任务,且模型保存加载流程正常。

2. 生成BIO格式标记代码

要实现BIO标记,需要遍历每个token并判断其是否属于实体、是实体的开头还是中间部分,代码示例:

# 可选:映射spaCy的NER标签到你需要的简写(比如PERSON→per)
label_mapping = {
    "PERSON": "per",
    "ORG": "org",
    "GPE": "loc",
    "DATE": "date",
    # 根据需求添加更多映射
}

ner_structured_docs = []
for doc_idx, doc in enumerate(train_docs):
    # 先记录每个token对应的实体标签
    token_ent_tags = {}
    for ent in doc.ents:
        # 获取实体对应的简写标签,没有映射则用原标签小写
        ner_label = label_mapping.get(ent.label_, ent.label_.lower())
        for token_idx in range(ent.start, ent.end):
            # 第一个token标记为B,后续为I
            tag_prefix = "B" if token_idx == ent.start else "I"
            token_ent_tags[token_idx] = f"{tag_prefix}-{ner_label}"
    
    # 遍历每个token生成最终标记
    for token_idx, token in enumerate(doc):
        # 非实体token标记为O
        final_tag = token_ent_tags.get(token_idx, "O")
        ner_structured_docs.append([doc_idx, token.text, final_tag])

代码说明

  • 先遍历所有实体,为每个实体包含的token分配B/I标签
  • 再遍历每个token,存在实体标记则使用对应标签,否则标记为O
  • 可通过label_mapping将spaCy的标准NER标签(如PERSON)转换为你需要的简写(如per)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:23:15