谷歌推出的Bert,最近有多火,估计做自然语言处理的都知道。据称在SQuAD等11项任务当中达到了state of the art。bert的原理可参考论文,或者网上其他人翻译的资料。谷歌已经在github上开源了代码,相信每一个从事NLP的都应该和我一样摩拳擦掌,迫不及待地想要学习它了吧。
就我个人而言学习一个开源项目,第一步是安装,第二步是跑下demo,第三步才是阅读源码。安装bert简单,直接github上拉下来就可以了,跑demo其实也不难,参照README.md一步步操作就行了,但是经我实操过后,发现里面有个小坑,所以用这篇文章记录下来,供读者参考。
闲言少叙,书归正传。本次介绍的demo只有两个,一个是基于MRPC(Microsoft Research Paraphrase Corpus )的句子对分类任务,一个是基于SQuAD语料的阅读理解任务。run demo分为以下几步:
1、下载bert源码
这没什么好说的,直接clone
git clone https://github.com/google-research/bert.git
2、下载预训练模型
为什么选择BERT-Base, Uncased
这个模型呢?原因有三:1、训练语料为英文,所以不选择中文或者多语种;2、设备条件有限,如果您的显卡内存小于16个G,那就请乖乖选择base,不要折腾large了;3、cased表示区分大小写,uncased表示不区分大小写。除非你明确知道你的任务对大小写敏感(比如命名实体识别、词性标注等)那么通常情况下uncased效果更好。
3、下载训练数据:
(1)下载MRPC语料:
官网上指定的方式是通过跑脚本download_glue_data.py来下载 GLUE data 。指定数据存放地址为:glue_data, 下载任务为:MRPC,执行(本篇中所有python3的命令同样适用于python):
python3 download_glue_data.py --data_dir glue_data --tasks MRPC
执行后发现下载失败,究其原因是下面这两个链接访问不上,几天后试了一次又能下载了,可能对方服务端不稳定。
MRPC_TRAIN = 'https://s3.amazonaws.com/senteval/senteval_data/msr_paraphrase_train.txt'
MRPC_TEST = 'https://s3.amazonaws.com/senteval/senteval_data/msr_paraphrase_test.txt'
如果不能下载,可以参考我当时的做法:
1、手动下载dev_ids.tsv映射表保存在glue_data/MRPC文件夹下
"MRPC":'https://firebasestorage.googleapis.com/v0/b/mtl-sentence-representations.appspot.com/o/data%2Fmrpc_dev_ids.tsv?alt=media&token=ec5c0836-31d5-48f4-b431-7480817f1adc',
2、因为 GLUE data官网也访问不了,所以只能去微软官网下载:https://www.microsoft.com/en-ca/download/details.aspx?id=52398
将 msr_paraphrase_test.txt, msr_paraphrase_train.txt两个解压后的文件放在mrpc_ori_corpus文件夹下
3、注释掉脚本download_glue_data.py里下载dev_ids.tsv文件的语句(如果你的服务器能下载可以不注释,使用代码下载不必手动下载):
65 # urllib.request.urlretrieve(TASK2PATH["MRPC"], os.path.join(mrpc_dir, "dev_ids.tsv"))
执行
python3 download_glue_data.py --data_dir glue_data --tasks MRPC --path_to_mrpc mrpc_ori_corpus
如果在glue_data/MRPC文件下出现 dev.tsv,test.tsv,train.tsv这三个文件,说明MRPC语料下载成功。
(2)下载SQuAD语料:
基本上没什么波折,可以使用下面三个链接直接下载,放置于$SQUAD_DIR路径下
4、run demo
(1) 基于MRPC语料的句子对分类任务
训练:
设置环境变量,指定预训练模型文件和语料地址
export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12
export GLUE_DIR=/path/to/glue_data
在bert源码文件里执行run_classifier.py,基于预训练模型进行fine-tune
python run_classifier.py \
--task_name=MRPC \
--do_train=true \
--do_eval=true \
--data_dir=$GLUE_DIR/MRPC \
--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=128 \
--train_batch_size=32 \
--learning_rate=2e-5 \
--num_train_epochs=3.0 \
--output_dir=/tmp/mrpc_output/
模型保存在output_dir, 验证结果为:
***** Eval results *****
eval_accuracy = 0.845588
eval_loss = 0.505248
global_step = 343
loss = 0.505248
预测:
指定fine-tune之后模型文件所在地址
export TRAINED_CLASSIFIER=/path/to/fine/tuned/classifier
执行以下语句完成预测任务,预测结果输出在output_dir文件夹中
python run_classifier.py \
--task_name=MRPC \
--do_predict=true \
--data_dir=$GLUE_DIR/MRPC \
--vocab_file=$BERT_BASE_DIR/vocab.txt \
--bert_config_file=$BERT_BASE_DIR/bert_config.json \
--init_checkpoint=$TRAINED_CLASSIFIER \
--max_seq_length=128 \
--output_dir=/tmp/mrpc_output/
(2)基于SQuAD语料的阅读理解任务
设置为语料所在文件夹为$SQUAD_DIR
python run_squad.py \
--vocab_file=$BERT_BASE_DIR/vocab.txt \
--bert_config_file=$BERT_BASE_DIR/bert_config.json \
--init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
--do_train=True \
--train_file=$SQUAD_DIR/train-v1.1.json \
--do_predict=True \
--predict_file=$SQUAD_DIR/dev-v1.1.json \
--train_batch_size=12 \
--learning_rate=3e-5 \
--num_train_epochs=2.0 \
--max_seq_length=384 \
--doc_stride=128 \
--output_dir=/tmp/squad_base/
在output_dir文件夹下会输出一个predictions.json文件,执行:
python3 $SQUAD_DIR/evaluate-v1.1.py $SQUAD_DIR/dev-v1.1.json predictions.json
看到以下结果,说明执行无误:
{"f1": 88.41249612335034, "exact_match": 81.2488174077578}
5、总结:
本篇内容主要解决了以下两个问题:
(1) 基于MRPC语料的句子对分类任务和基于SQuAD语料的阅读理解任务的demo执行,主要是翻译源码中README.md的部分内容;
(2) 对于部分语料无法下载的情况,提供了其他的搜集方式。
系列后续将对bert源码进行解读,敬请关注
系列文章
Bert系列(二)——模型主体源码解读
Bert系列(三)——源码解读之Pre-train
Bert系列(四)——源码解读之Fine-tune
Bert系列(五)——中文分词实践 F1 97.8%(附代码)
Reference
1.https://github.com/google-research/bert