当前位置:   article > 正文

转化BIO命名实体识别(NER)数据格式_bio格式

bio格式

bug

该代码有一些bug,可查看评论区,已有读者指出
可参考如下代码修复该bug

简介

BIO命名实体标注格式如下:
(数据太多行,只展示一部分数据)

可 O
见 O
...
宋 B-PER
神 I-PER
宗 I-PER
时 O
, O
官 O
拜 O
礼 B-ORG
部 I-ORG
郎 O
杨 B-PER
次 I-PER
公 I-PER
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

上述BIO形式数据,通常使用分类算法进行训练。
然而对于一些生成式的模型,无法使用上述数据集。
故本文实现转换BIO数据集为如下形式:

['可见牧牛图是根据宋神宗时,官拜礼部郎杨次公的“牧牛颂”而创作的。', [('宋神宗', 'PER'), ('礼部', 'ORG'), ('杨次公', 'PER')]]
  • 1

提供了列表格式的数据,便于用户修改与自定义转换数据格式。

代码实现

file = 'data/test.txt'

with open(file, 'r', encoding='utf-8') as f:
    texts = f.read().rstrip()
    data = texts.split('\n\n')
    total = []
    for i in range(len(data)):
        line = data[i].split('\n')
        start, end = 0, 0
        offsets = []  # 存储每个实体的起始下标位置和结束下标位置
        texts = []
        labels = []
        for idx, item in enumerate(line):
            word, label = item.split(' ')
            texts.append(word)
            labels.append(label)
            if label[0] == 'B':
                if start and end:
                    offsets.append((start, end))
                start, end = idx, 0
            if label == 'O':
                if start and not end:
                    end = idx
        if start and end:
            offsets.append((start, end))

        texts = ''.join(texts)
        ents = [
            (texts[start:end], labels[start][2:])
            for start, end in offsets
        ]

        total.append([
            texts,
            ents
        ])

    for line in total:
        print(line)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

上述代码的offsets存储的是实体的开始下标和结束下标。若您希望得到实体的下标,请关注offsets变量。

实验

输入:file = 'data/test.txt' 为 BIO数据集的文件路径;
输出:

['我们变而以书会友,以书结缘,把欧美、港台流行的食品类图谱、画册、工具书汇集一堂。', [('美', 'LOC'), ('台', 'LOC')]]
['为了跟踪国际最新食品工艺、流行趋势,大量搜集海外专业书刊资料是提高技艺的捷径。', []]
['其中线装古籍逾千册;民国出版物几百种;珍本四册、稀见本四百余册,出版时间跨越三百余年。', []]
...
  • 1
  • 2
  • 3
  • 4

扩展应用

借助于上述代码将BIO数据,转换为下述格式(该格式为Deepke的命名实体识别格式):

{"text": "我们变而以书会友,以书结缘,把欧美、港台流行的食品类图谱、画册、工具书汇集一堂。", "entity": [{"entity": "美", "entity_type": "LOC"}, {"entity": "台", "entity_type": "LOC"}]}
  • 1

代码

实现从文件到文件的转换,方便使用;

import json


def convert(input_file, output_file):
    def _iter_data():
        with open(input_file, 'r', encoding='utf-8') as f:
            texts = f.read().rstrip()
            data = texts.split('\n\n')

            for i in range(len(data)):
                line = data[i].split('\n')
                start, end = 0, 0
                offsets = []  # 存储每个实体的起始下标位置和结束下标位置
                texts = []
                labels = []
                for idx, item in enumerate(line):
                    word, label = item.split(' ')
                    texts.append(word)
                    labels.append(label)
                    if label[0] == 'B':
                        if start and end:
                            offsets.append((start, end))
                        start, end = idx, 0
                    if label == 'O':
                        if start and not end:
                            end = idx
                if start and end:
                    offsets.append((start, end))

                texts = ''.join(texts)
                ents = [
                    (texts[start:end], labels[start][2:])
                    for start, end in offsets
                ]

                yield {
                    "text": texts,
                    "entity": [
                        {'entity': entity, 'entity_type': entity_type}
                        for entity, entity_type in ents
                    ]
                }

    with open(output_file, 'w', encoding='utf-8') as f:
        for item in _iter_data():
            f.write(json.dumps(item, ensure_ascii=False) + '\n')


if __name__ == '__main__':
    convert('data/test.txt', 'output/test.json')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/788809
推荐阅读
相关标签
  

闽ICP备14008679号