使用BERT + Bi-LSTM + CRF 实现命名实体识别

本文详细解析了使用BERT、LSTM与CRF结合实现命名实体识别(NER)的技术流程,涵盖数据预处理、模型架构及训练等多个方面。

1.前言

  • 本文主要分析本次实验的代码,讲解主要流程和代码含义,并不关注参数的选择和模型的选择
  • 后续可能还会更新 model 的原理
  • 如果有问题,欢迎评论或私聊讨论
  • 若分析过程出现错误,请及时指正,谢谢

2.数据预处理

  • 原始标注:对句子中的每个字标注上一个标签,可以简单地看成是直接对每个字分类(需要融合上下文信息),因此可以使用一个多分类器,分类器输出类别就是该字的标签
  • 联合标注:对一串连续的字标注相同的标签。在NER任务中,实体由一个或多个字组成,所以它属于联合标注任务

但是在联合标注中,相邻词语标签之间可能会存在依赖关系。这一问题可以通过标签转化的方式,把联合标注转化成原始标注解决。

我们这里使用的是BIOS标注

标签 含义
B-X 该字是词片段 X 的起始字
I-X 该字是词片段 X 起始字之后的字
S-X 该字单独标记为 X 标签
O 该字不属于事先定义的任何词片段类型

process.py中,我们将.json文件中的语句和标签,按照BIOS方式,处理转换成了.npz文件。主要代码如下。分析过程写在注释中,依据样例.json

text = json_line['text']
words = list(text)  # 自动将句子按字符分开
# 如果没有label,则返回None
label_entities = json_line.get('label', None)  # 参照下面的例子, 该项对应 label 之后的内容
labels = ['O'] * len(words)  # [len(words) 个 'O'] 都初始化为 `O`

if label_entities is not None:
    for key, value in label_entities.items():  # key 对应 name 和 company, value 对应后面存储内容
        for sub_name, sub_index in value.items():  # sub_name 对应 叶老桂等, sub_value 对应后面的索引
            for start_index, end_index in sub_index:  # 对应列表中的两个数,是标签开始和结束的位置
                assert ''.join(words[start_index:end_index + 1]) == sub_name
                if start_index == end_index:  # 单个字作为索引
                    labels[start_index] = 'S-' + key
                    else:
                        labels[start_index] = 'B-' + key  # 开头
                        labels[start_index + 1:end_index + 1] = ['I-' + key] * (len(sub_name) - 1)  # 中间的字
  • 字符串转 list验证

    • 这里很重要的一点是,输入的字符串都转成单字符了,下面使用 tokenize 的时候会看到为什么
    a = "你好,我是nsy,哈哈哈"
    print(list(a))
    >>['你', '好', ',', '我', '是', 'n', 's', 'y', ',', '哈', '哈', '哈']
    

.json文件中,数据存储结构如下所示

{
   
   
	"text": "浙商银行企业信贷部叶老桂博士则从另一个角度对五道门槛进行了解读。叶老桂认为,对目前国内商业银行而言,",
	"label": {
   
   
		"name": {
   
   
			"叶老桂": [
				[9, 11],
				[32, 34]
			]
		},
		"company": {
   
   
			"浙商银行": [
				[0, 3]
			]
		}
	}
}

2.1本地查看数据转换后的结果

  • code

    import numpy as np
    a = np.load(r'D:\2022 spring\nlp\exp4\code\BERT-LSTM-CRF\data\clue\test.npz', allow_pickle=True)
    index = 0
    words = a['words']
    labels = a['labels']
    print(words[0])
    print(labels[0])
    
  • 结果

    ['彭
评论 50
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长命百岁️

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值