2019达观杯实体识别
2019达观杯,实体识别代码分享。
该比赛将文本全部为编码,所以需要自行做预训练。由于当时在做其他比赛和准备参展人工智能大会,所以大致用了3天初步训练了word2vec和BERT,并没有深入研究,代码仅供参考。
比赛本身是一个相对简单的实体识别任务,难点主要在预训练上。所以该比赛可以尝试以下方案:
1.仅使用训练数据,用embedding的方式随网络一起训练;
2.根据给的百万语料,自行训练word2vec,做成权重矩阵载入embedding层,此处我使用gensim来训练;
3.根据给的百万语料,自行训练BERT,我使用tf官方bert脚本来训练;
1.运行python make_corpus.py
,构建语料(里面的字典可以不构建,看到底需不需要全部词语词向量),词频从高到低,去掉词频为1的;
2.运行python train_word2vec.py --size 300 --sg 1 --workers 6
,用gensim训练word2vec,自行参考gensim函数说明修改epoch等参数,耗时较长建议后台运行,大概30-60分钟不等,取决于你的参数;
3.运行python make_weight.py --size 300 --sg 1 &
,结合词典(如果做了的话)和gensim模型,生成embedding权重;
本次比赛的重头戏,我也是第一次自己训练,还是觉得有点成就感的。采用谷歌官方脚本:https://github.com/google-research/bert,
1.运行python make_corpus.py
,构建语料(里面的字典可以不构建,看到底需不需要全部词语),把训练集、测试集、语料集都合并进texts_all.txt中,空格分隔;
2.运行python make_vocab.py
,用到了之前生成字典,当然你也可以不用,主要看你的vocab到底需不需要全部词语;
3.运行python create_pretraining_data.py --input_file=./data/texts_all.txt --output_file=./data/texts_all_160_24_4_1.tfrecord --vocab_file=./data/vocab.txt --do_lower_case=True --max_seq_length=160 --max_predictions_per_seq=24 --masked_lm_prob=0.15 --random_seed=4 --dupe_factor=1
,构建语料,耗时较长建议后台运行;
4.运行CUDA_VISIBLE_DEVICES=0 python run_pretraining.py --input_file=./data/texts_all_160_24_1_1.tfrecord --output_dir=./models/texts_all_160_24_1_1/ --do_train=True --do_eval=True --bert_config_file=./data/bert_config.json --train_batch_size=32 --eval_batch_size=8 --max_seq_length=160 --max_predictions_per_seq=24 --num_train_steps=100000 --num_warmup_steps=10000 --learning_rate=5e-5 --save_checkpoints_steps 2000 --iterations_per_loop 2000
,耗时较长建议后台运行,1080ti需要若干天(取决于你的参数),不支持分布式,原因不详,所以我用了4块卡分别训练了4个不同种子的模型;
5.运行python convert_tf_checkpoint_to_pytorch.py --tf_checkpoint_path ./try/model.ckpt-28000 --bert_config_file ./try/bert_config.json --pytorch_dump_path ./try/pytorch_model.bin
,转为pytorch模型,如果你是tf选手可以忽略此步;
这个没啥含金量,无非是crf、指针网络等思路,各种比赛都差不多。
1.运行python train.py --cuda 3 --pretrain texts_all_160_24_4_1_100000 --num_layers 3 --hidden_dim 768 --loss_weight 3 --epochs 25 --k 0.865 --size 768
(3号卡、预训练名为texts_all_160_24_4_1_100000、3层、lstm768、损失权重比3、25个epoch、模型保存阈值0.865、bert模型输出维度);
2.运行python submit_test.py
,选择模型输出结果的名称,生成提交结果;
只花了一点点的时间做预训练,多训练几轮的效果会有显著提升;
预训练Model | 线上得分(单模) | 线上得分(融合) |
---|---|---|
无 | 0.840 | 0.860 |
word2vec(epoch=3,dim=300) | 0.860 | 0.880 |
word2vec(epoch=5,dim=300) | 0.865 | 0.885 |
bert(dupe_factor=1,num_train_steps=30000) | 0.875 | 0.900 |
bert(dupe_factor=1,num_train_steps=80000) | 0.885 | 0.905 |
bert(dupe_factor=1,num_train_steps=200000) | 0.900 | 没做 |
bert(dupe_factor=4,num_train_steps=100000) | 0.895 | 没做 |
因为最近讨论bert的一些细节,才记起来有这个比赛。当初只是练手训练bert,而且做的时候离结束就剩一周时间,所以没怎么深挖,如有问题请自行debug。整体应该没啥大问题,因为我线上提交过4次,对主办方提供比赛数据表示感谢。
性能:我自己用的是1080ti,bert(max_seq_length=160,train_batch_size=32,num_train_steps=20000)单卡大约5h;朋友用v100(16g)帮忙跑了bert(max_seq_length=160,train_batch_size=32,num_train_steps=200000),单卡大约1.5天。