如何使用pickle文件训练Spacy NER模型并完成数据格式转换?
数据格式转换操作步骤
你当前持有的是存储在pickle文件中的BIO序列标注数据,每条样本由「(词, 词性) + 实体标注标签」的二元组组成,spaCy要求的训练数据为「原始文本 + 实体起止位置标注」的格式,你可以按照以下步骤完成转换:
- 加载pickle原始数据
调用pickle.load()读取本地pickle文件,得到完整的嵌套列表格式的标注数据集。 - 逐样本拼接文本并记录词的位置偏移
遍历单条样本的所有词,按空格拼接得到完整的句子字符串,同时维护当前字符偏移量,依次记录每个词对应的起始下标和结束下标:注意拼接时的空格会占用1个字符长度,计算下一个词的起始位置时要额外加1。 - 解析BIO标签合并实体
遍历同一样本中每个词的标签和对应的位置:- 碰到
B-开头的标签,说明是新实体的起始,记录当前实体的开始下标,同时提取实体类型(去掉标签前缀B-即可) - 碰到
I-开头的标签,说明属于当前未闭合的实体,更新实体的结束下标为当前词的结束下标 - 碰到
O标签,如果当前有未保存的实体,就将「(实体起始下标, 实体结束下标, 实体类型)」存入当前样本的实体列表
- 碰到
- 组装成目标格式
将单条样本的完整文本字符串和存储实体的字典{"entities": 实体列表}组装为元组,所有样本处理完成后即可得到符合spaCy要求的训练数据集。
示例参考代码
import pickle # 1. 加载原始数据 with open("你的数据文件路径.pkl", "rb") as f: raw_data = pickle.load(f) TRAIN_DATA = [] for sample in raw_data: text = "" offset = 0 word_positions = [] # 2. 拼接文本并记录每个词的位置 for (word, pos), tag in sample: start = offset end = offset + len(word) word_positions.append((start, end, tag)) text += word + " " offset = end + 1 # 去掉最后多余的空格 text = text.rstrip() # 3. 解析BIO合并实体 entities = [] current_entity = None for start, end, tag in word_positions: if tag.startswith("B-"): # 之前有未保存的实体先存起来 if current_entity is not None: entities.append(tuple(current_entity)) entity_type = tag.split("-")[1] current_entity = [start, end, entity_type] elif tag.startswith("I-"): if current_entity is not None: # 更新实体结束位置 current_entity[1] = end else: # O标签 if current_entity is not None: entities.append(tuple(current_entity)) current_entity = None # 最后检查有没有漏存的实体 if current_entity is not None: entities.append(tuple(current_entity)) # 4. 组装成目标格式 TRAIN_DATA.append((text, {"entities": entities}))
内容的提问来源于stack exchange,提问作者hidden layer
相关产品推荐
相关产品推荐

