实体标注的 BIO 标签怎么生成?用字符偏移检查跨词与冲突

实体识别训练数据常把连续文本片段转成 B-ORG、I-ORG 等逐词标签。关键不是随意给词打标,而是先确认字符偏移与分词边界完全对齐:一个实体可跨多个词,冲突或半个词的片段必须退回修订。

实体识别训练数据常把连续文本片段转成 B-ORG、I-ORG 等逐词标签。关键不是随意给词打标,而是先确认字符偏移与分词边界完全对齐:一个实体可跨多个词,冲突或半个词的片段必须退回修订。

准备与运行

本文只使用人工构造的教学材料,没有把示例结果当作真实项目效果。以下代码在 Windows 的 Python 3.11 独立环境执行通过。先在空目录运行安装命令,再将完整代码保存为 demo.py,执行 python demo.py。

实体标注的 BIO 标签怎么生成?用字符偏移检查跨词与冲突

python --version  # 只用 Python 标准库

用字符区间固定原文位置

教学句子是“北京大学在北京招生”。先记录每个词在原句中的左闭右开区间;“北京大学”作为机构跨“北京”“大学”两个词,生成 B-ORG、I-ORG。“北京”地名位于后半句,生成 B-LOC。同样的字在不同位置承担不同标签,所以仅按字面搜索会误标第一处“北京”。

代码用实体的 start、end 与词起止位置对齐。若实体从一个词中间开始,说明标注片段与当前分词方案冲突,应回到原文和标注规范处理。训练库中尤其要固定 Unicode 位置单位,不能把字节偏移、字符偏移和模型 token 索引混用。

冲突先报错,不做静默覆盖

算法先检查实体区间在原文内、非空且不互相覆盖,再检查开始和结束都落在词边界。覆盖两词的实体,第一个标 B,后续标 I;没有实体的词标 O。代码故意送入一个半词起点,确认它被拒绝。

实际项目还需处理嵌套实体、标点、数字和子词切分。这里的手工词边界只为演示 BIO 映射,不等于具体模型 tokenizer 的结果;若训练时再做子词拆分,还要确定子词标签策略并核对 offset mapping。

完整代码

text = "北京大学在北京招生"
tokens = [("北京",0,2),("大学",2,4),("在",4,5),("北京",5,7),("招生",7,9)]
entities = [(0,4,"ORG"),(5,7,"LOC")]

def to_bio(text, tokens, entities):
    boundaries = {0, len(text)} | {start for _,start,_ in tokens} | {end for _,_,end in tokens}
    assert "".join(word for word,_,_ in tokens) == text
    for word,start,end in tokens:
        if text[start:end] != word: raise ValueError("token_offset_mismatch")
    labels = ["O"] * len(tokens)
    previous_end = 0
    for start,end,kind in sorted(entities):
        if start < previous_end or not (0 <= start < end <= len(text)):
            raise ValueError("entity_overlap_or_range_error")
        if start not in boundaries or end not in boundaries:
            raise ValueError("entity_crosses_token_boundary")
        positions = [i for i,(_,a,b) in enumerate(tokens) if a >= start and b <= end]
        if not positions or tokens[positions[0]][1] != start or tokens[positions[-1]][2] != end:
            raise ValueError("entity_not_covered_by_tokens")
        for j,i in enumerate(positions): labels[i] = ("B-" if j == 0 else "I-") + kind
        previous_end = end
    return labels

labels = to_bio(text,tokens,entities)
print("token_and_BIO",list(zip([t[0] for t in tokens],labels)))
try:
    to_bio(text,tokens,[(1,4,"ORG")])
except ValueError as exc:
    print("bad_offset_rejected",str(exc))
else: raise AssertionError("bad offset accepted")
assert labels == ["B-ORG","I-ORG","O","B-LOC","O"]

运行结果与核对

下面是上述脚本在本地执行得到的输出;正式数据请按相同检查点复核。

token_and_BIO [('北京', 'B-ORG'), ('大学', 'I-ORG'), ('在', 'O'), ('北京', 'B-LOC'), ('招生', 'O')]
bad_offset_rejected entity_crosses_token_boundary

核对前两词分别为 B-ORG、I-ORG,第二处“北京”为 B-LOC;半词起点 (1,4) 必须显示 entity_crosses_token_boundary。若真实标注转成 BIO 时出现这个错误,回查原文偏移与分词版本,不要把片段直接四舍五入。

适用边界

这是人工切好的五个词及两处虚构标注,不涉及 Label Studio 界面,也没有训练实体模型。BIO 通常只能直接表达单层、不重叠的序列标签;嵌套实体需要另一套表示或任务设计。

常见问题

同一个词既是机构又是地点怎么办?

先回到任务定义与上下文确定标注目标;单层 BIO 不能在同一词上同时保存两个重叠实体。需要多层标注时应改数据表示,而非覆盖旧标签。

参考资料

以下官方资料已于 2026 年 10 月 1 日核对,分别用于确认文中接口或方法定义。

Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/31730.html

赞 (0)
AI小管家的头像AI小管家
中文文章怎么做抽取式摘要?选关键句并核对数字与实体
上一篇 2小时前
用 ChatGPT 纠错怎么防止改错事实?逐项核对数字和专有名词
下一篇 2小时前

相关推荐

联系我们

联系我们

1

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
关注微信
分享本页
返回顶部