如何将conllu文件中非IOB格式的命名实体标签转换为IOB格式
Conllu非IOB命名实体标签转IOB标签实现方案
原代码问题说明
- 正则表达式错误:使用行首匹配符
^不符合NE标签位于竖线分隔字段中的实际格式,无法匹配到目标内容 - 遍历逻辑错误:调用
next(line)会直接跳过下一行的遍历,导致文件行处理混乱 - 变量使用错误:
ne是匹配到的实体类型列表,直接拼接字符串会抛出类型错误 - 字符串修改未生效:
re.sub返回新字符串,原代码未将修改结果赋值,改动不会保留
正确实现方案
实现逻辑:
- 预编译正则匹配
NE=实体类型_数字格式的标签,提取实体类型和分组编号 - 维护上一个匹配到的实体分组标识(实体类型+编号),用来判断当前标签是实体开头(B)还是实体中间(I)
- 逐行处理后输出替换后的内容,自动备份原文件
import fileinput import re # 预定义实体类型 list_of_fields = ["PER", "ORG", "LOC", "GPE", "OTH"] # 预编译正则:匹配NE=类型_数字,分组1是实体类型,分组2是分组编号 ne_pattern = re.compile(rf'NE=({"|".join(list_of_fields)})_(\d+)') # 记录上一个匹配到的实体分组(类型+编号) last_ne_group = None # 替换为你的conllu文件路径 input_file = "你的输入文件路径.conllu" with fileinput.FileInput(input_file, inplace=True, backup=".bak") as f: for line in f: line = line.rstrip("\n") # 匹配当前行的NE标签 match_res = ne_pattern.search(line) if match_res: ne_type = match_res.group(1) ne_id = match_res.group(2) current_group = f"{ne_type}_{ne_id}" # 判断是B还是I if current_group == last_ne_group: replace_tag = f"NE=I-{ne_type}" else: replace_tag = f"NE=B-{ne_type}" # 替换内容 line = ne_pattern.sub(replace_tag, line) # 更新上一个分组 last_ne_group = current_group else: # 没有匹配到NE标签,清空上一个分组 last_ne_group = None # 输出行(inplace模式下print会直接写入文件) print(line)
使用说明
- 将代码中的
你的输入文件路径.conllu替换为实际的conllu文件路径 - 运行后原文件会被修改为IOB格式,原文件会自动备份为
原文件名.bak,处理出错可以从备份恢复 - 完全符合给定的转换规则,相同实体类型+相同编号的连续行,首行替换为B-前缀,后续行替换为I-前缀
内容的提问来源于stack exchange,提问作者darned7
相关产品推荐
相关产品推荐

