基于BERT的中文命名实体识别
代码和数据都存放在了github上:https://github.com/xuanzebi/BERT-CH-NER
欢迎大家STAR啊,来让我收获人生的第一个STAR吧 2333~~~~~
基于上课老师课程作业发布的中文数据集下使用BERT来训练命名实体识别NER任务。
之前也用了Bi+LSTM+CRF进行识别,效果也不错,这次使用BERT来进行训练,也算是对BERT源码进行一个阅读和理解吧。
虽然之前网上也有很多使用BERT的例子和教程,但是我觉得都不是很完整,有些缺乏注释对新手不太友好,有些则是问题不同修改的代码也不同,自己也在路上遇到了不少的坑。所以记录一下。
数据集
tmp 文件夹下
如上图,对数据集进行了分割,其中source是训练集中文,target是训练集的label。
test1 测试集,test_tgt 测试集label。 dev 验证集 dev-lable 验证集label。
类别
其*设置了10个类别,PAD是当句子长度未达到max_seq_length时,补充0的类别。
CLS是每个句首前加一个标志[CLS]的类别,SEP是句尾同理。(因为BERT处理句子是会在句首句尾加上这两个符号。)
代码
其实BERT需要根据具体的问题来修改相对应的代码,NER算是序列标注一类的问题,可以算分类问题吧。
然后修改的主要是run_classifier.py部分即可,我把修改下游任务后的代码放到了run_NER.py里。
之后会对其需要修改的部分进行解释。
待更新== 这个更新会在github上更新,欢迎关注。
训练
首先下载BERT基于中文预训练的模型,
export BERT_BASE_DIR=/opt/xxx/chinese_L-12_H-768_A-12
export NER_DIR=/opt/xxx/tmp
python run_NER.py \
--task_name=NER \
--do_train=true \
--do_eval=true \
--do_predict=true \
--data_dir=$NER_DIR/ \
--vocab_file=$BERT_BASE_DIR/vocab.txt \
--bert_config_file=$BERT_BASE_DIR/bert_config.json \
--init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
--max_seq_length=256 \ # 根据实际句子长度可调
--train_batch_size=32 \ # 可调
--learning_rate=2e-5 \
--num_train_epochs=3.0 \
--output_dir=$BERT_BASE_DIR/output/
来看训练时候的一个样例,其中input_ids是把词根据词表转换为数字,长度没有达到max_seq_len使用0填充。
input_mask 填充的为0,真实数据长度为1.
segment_ids 这个是因为BERT有的是可以使用句子的下一个句子来一起训练,所以是来分别句子类别的,第一个句子全为0,第二个句子则为1.
label_ids就是你需要的label这个自己设置。
实验结果
可以基于验证集看到的准确率召回率都在95%以上。
下面可以看看预测测试集的几个例子。
下图为使用BERT预测的类别。可以与真实的类别对比看到预测还是很准确的。
真实类别如下图。
总结
其实在读了BERT的论文后,结合代码进行下游任务的微调能够理解的更深刻。
其实改造下游任务主要是把自己数据改造成它们需要的格式,然后将输出类别根据需要改一下,然后模型的metric函数改一下就整体差不多了。
如下图根据具体的下游任务修改label即可。如下图的第四个就是在NER上进行修改,
参考 :
https://github.com/google-research/bert 官方
https://github.com/kyzhouhzau/BERT-NER 基于英文的NER,但是代码注释不太多。
有时间了更新剩下的readme 、 包括对源码的注释和如何根据NER下游任务来修改代码等====
欢迎STAR