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

NER数据集处理:删除无实体句子并更新标注偏移方法咨询

NER标注数据集无标注句子清理及偏移修正方案

核心实现代码

import re
from typing import List, Dict

def clean_ner_data(original_data: List[Dict]) -> List[Dict]:
    result = []
    # 正则匹配句子边界,可根据实际语料调整,当前默认适配英文句号+空格/换行的场景
    sentence_pattern = re.compile(r'([^.!?]+[.!?])(\s|\n)*')
    
    for item in original_data:
        content = item["content"]
        annotations = item["annotations"]
        # 1. 拆分所有句子,记录每个句子在原文中的起始、结束偏移
        sentences = []
        for match in sentence_pattern.finditer(content):
            sent_start = match.start(1)
            sent_end = match.end(1)
            sentences.append({
                "text": match.group(1),
                "start": sent_start,
                "end": sent_end,
                "has_entity": False,
                "entities": []
            })
        # 2. 匹配每个实体所属的句子
        for ent in annotations:
            ent_start = ent["start"]
            ent_end = ent["end"]
            for sent in sentences:
                if sent["start"] <= ent_start and ent_end <= sent["end"]:
                    sent["has_entity"] = True
                    sent["entities"].append(ent.copy())
                    break
        # 3. 筛选保留含实体的句子,计算偏移修正量
        new_content = ""
        new_annotations = []
        # 累计删除内容的总长度,用于修正实体偏移
        deleted_length = 0
        prev_sent_end = 0
        for sent in sentences:
            # 计算当前句子与上一个句子之间的间隔长度(空格、换行等)
            interval_length = sent["start"] - prev_sent_end
            if not sent["has_entity"]:
                # 无实体句子,累计删除长度
                deleted_length += interval_length + (sent["end"] - sent["start"])
            else:
                # 保留有实体的句子,按规则拼接
                if new_content:
                    new_content += " "
                new_content += sent["text"]
                # 修正该句子下所有实体的偏移值
                for ent in sent["entities"]:
                    new_ent = ent.copy()
                    new_ent["start"] = ent["start"] - deleted_length
                    new_ent["end"] = ent["end"] - deleted_length
                    new_annotations.append(new_ent)
            prev_sent_end = sent["end"]
        # 组装单条数据结果
        result.append({
            "content": new_content,
            "annotations": new_annotations
        })
    return result

# 测试示例
if __name__ == "__main__":
    data = [{"content":'''Hello I am Aniyya. I enjoy playing Football.
I love eating grapes''',"annotations":[{"id":1,"start":11,"end":17,"tag":"name"},
                                    {"id":2,"start":59,"end":65,"tag":"fruit"}]}]
    result_data = clean_ner_data(data)
    print(result_data)

实现说明

  • 默认适配英文句子边界规则,处理中文语料时可将句子匹配正则替换为适配中文句号、问号、感叹号的规则即可
  • 现有逻辑默认跳过跨句子实体,若标注存在跨句实体,可自行补充对应处理逻辑
  • 拼接保留句子时默认使用单个空格分隔,若需保留原有的换行、多空格格式,可调整间隔处理部分的逻辑

运行上述测试用例输出的结果与预期格式完全一致,实体偏移会自动修正为正确值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 09:15:07