Are you sure you want to delete this task? Once this task is deleted, it cannot be recovered.
Jiaqi Liu b47de842c5 | 2 years ago | |
---|---|---|
.. | ||
imgs | 2 years ago | |
README.md | 2 years ago | |
data_augmentation.py | 2 years ago | |
general_distill.py | 2 years ago | |
task_distill.py | 2 years ago |
以下是本例的简要目录结构及说明:
.
├── task_distill.py # 在特定任务上下的蒸馏脚本
├── data_augmentation.py # 离线数据增强脚本
└── README.md # 文档,本文件
本目录下的实验主要参考论文《TinyBERT: Distilling BERT for Natural Language Understanding》实现。
TinyBERT中蒸馏的整体过程:首先进行通用蒸馏,然后用数据增强后的数据,在特定任务上进行蒸馏,本文主要进行了第二阶段的蒸馏,模型是利用第一阶段得到的通用小模型tinybert-6l-768d-v2
进行初始化。
TinyBERT蒸馏流程图
在模型蒸馏中,较大的模型(在本例中是BERT base)通常被称为教师模型,较小的模型(在本例中是层数为6的BERT,下文都称TinyBERT6)通常被称为学生模型。
知识的蒸馏通常是通过让学生模型学习相关的蒸馏相损失函数实现,在本实验中,蒸馏的学习目标由两个部分组成,分别是中间层的蒸馏损失和预测层的蒸馏损失。其中,中间层的蒸馏包括对Embedding层的蒸馏、对每个Transformer layer输出的蒸馏、以及对每个Transformer中attention矩阵(softmax之前的结果)的蒸馏,三者均采用的是均方误差损失函数。而预测层蒸馏的学习目标则是学生模型输出的logits和教师模型输出的logits的交叉熵损失。
由于教师模型是12层,学生模型的层数少于教师模型的层数,因此需要选择一种layer mapping的方式。论文中采用了一种固定的映射方式,当学生模型的层数为教师模型的1/2时,学生第i层的attention矩阵,需要学习教师的第2i+1层的attention矩阵,Transformer layer输出同理。
实验分为两个大的训练过程:先对BERT-base进行微调,得到教师模型,再进行蒸馏的训练。其中,蒸馏过程也分为两个步骤:先对中间层进行蒸馏多个epochs(论文中针对具体任务可能是10、20或者30个),再对预测层蒸馏3个epochs。
需要注意的是,在使用不同教师模型时,tinybert-6l-768d-v2
、tinybert-4l-312d-v2
这两个v2版本的预训练模型中开放的从学生embedding输出、transformer中间层输出到教师相应输出的转换矩阵是每层独立的,而其他的tinybert-6l-768d
、tinybert-4l-312d
、tinybert-6l-768d-zh
、tinybert-4l-312-zh
则是多层之间的参数共用一个转换矩阵的。
本实验使用GLUE中数据集中的训练集作为训练语料,用数据集中的验证集评估模型的效果。
运行本目录下的实验,数据集会被自动下载到paddlenlp.utils.env.DATA_HOME
路径下,例如在linux系统下,对于GLUE中的QQP数据集,默认存储路径是~/.paddlenlp/datasets/Glue/QQP
。
对于BERT的fine-tuning任务,本实验中使用了预训练模型bert-base-uncased
。同样,这几个模型在训练时会被自动下载到paddlenlp.utils.env.MODEL_HOME
路径下。例如,对于bert-base-uncased
模型,在linux系统下,会被下载到~/.paddlenlp/models/bert-base-uncased
下。
以GLUE的SST-2任务为例,调用BERT fine-tune的训练脚本,配置如下的参数,训练SST-2任务:
cd ../../benchmark/glue/
export CUDA_VISIBLE_DEVICES=0
export TASK_NAME=SST-2
python -u ./run_glue.py \
--model_type bert \
--model_name_or_path bert-base-uncased \
--task_name $TASK_NAME \
--max_seq_length 128 \
--batch_size 32 \
--learning_rate 2e-5 \
--num_train_epochs 3 \
--logging_steps 1 \
--save_steps 500 \
--output_dir ./tmp/$TASK_NAME/ \
--device gpu \
训练完成之后,可将训练效果最好的模型保存在本项目下的pretrained_models/$TASK_NAME/
下。模型目录下有model_config.json
, model_state.pdparams
, tokenizer_config.json
及vocab.txt
这几个文件。
先蒸馏中间层:
export CUDA_VISIBLE_DEVICES=0
export TASK_NAME=SST-2
export TEACHER_DIR=../pretrained_models/SST-2/best_model_610
python task_distill.py \
--model_type tinybert \
--student_model_name_or_path tinybert-6l-768d-v2 \
--task_name $TASK_NAME \
--intermediate_distill \
--max_seq_length 64 \
--batch_size 32 \
--T 1 \
--teacher_model_type bert \
--teacher_path $TEACHER_DIR \
--learning_rate 5e-5 \
--num_train_epochs 20 \
--logging_steps 10 \
--save_steps 10 \
--output_dir ./tmp/$TASK_NAME/ \
--device gpu
其中参数释义如下:
model_type
学生模型类型,默认且目前仅支持tinybert。student_model_name_or_path
中间层蒸馏后,学生模型存放的目录max_seq_length
表示最大句子长度,超过该长度将被截断。默认:128T
softmax的温度,用于对softmax做平滑,在训练中起到放大负标签效果的作用。默认:1teacher_model_type
教师模型的类型,默认且目前仅支持bertteacher_path
教师Fine-tuned模型的目录output_dir
学生模型存放的目录device
表示运行该程序的设备,默认是gpu然后对预测层进行蒸馏:
export TEACHER_DIR=../pretrained_models/SST-2/best_model_610
python task_distill.py \
--model_type tinybert \
--student_model_name_or_path tmp/TASK_NAME best_inter_model \
--task_name $TASK_NAME \
--max_seq_length 64 \
--batch_size 32 \
--T 1 \
--teacher_model_type bert \
--teacher_path $TEACHER_DIR \
--learning_rate 3e-5 \
--num_train_epochs 3 \
--logging_steps 10 \
--save_steps 10 \
--output_dir ./tmp/$TASK_NAME/ \
--device gpu
其中参数释义如下:
student_model_name_or_path
中间层蒸馏后,学生模型存放的目录SST-2 | QQP | MRPC | CoLA | RTE | MNLI | QNLI | |
---|---|---|---|---|---|---|---|
batch_size | 32 | 32 | 32 | 32 | 32 | 32 | 32 |
max_seq_length | 64 | 128 | 128 | 64 | 128 | 128 | 128 |
max_epochs_of_intermediate_layer | 20 | 10 | 20 | 50 | 20 | 10 | 10 |
max_epochs_of_prediction_layer | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
learning_rate(inter/pred) | 5e-5/3e-5 | 5e-5/3e-5 | 5e-5/3e-5 | 5e-5/3e-5 | 5e-5/3e-5 | 5e-5/3e-5 | 5e-5/3e-5 |
本文档的实验基于TinyBERT的6层、hidden_size为768的通用蒸馏得到的模型,用未使用数据增强的原始数据集训练,并基于验证集进行评价。得到以下实验结果:
SST-2 | QQP(acc/f1) | MRPC(acc/f1) | CoLA | RTE | MNLI-m | MNLI-mm | QNLI | |
---|---|---|---|---|---|---|---|---|
BERT-base | 93.00 | 90.58/87.35 | 88.23/91.67 | 59.56 | 73.65 | 84.42 | 84.83 | 91.78 |
TinyBERT(6l-768d) | 93.00 | 91.13/88.20 | 88.48/91.91 | 52.64 | 72.94 | 84.57 | 84.63 | 91.36 |
TinyBERT使用的数据增强需要用到BERT预训练模型和Glove Embeddings做词替换。
即对于样本中的词,有一定的概率会被近义词替换。对于single-piece的词,会利用BERT的预训练模型,把选中的词替换成mask token,然后返回模型预测的top k个概率最大的词,最后随机选择其中一个词做替换;对于非single-piece的词,则使用Glove Embedding,找到top k个最近似的词,随机选择一个做替换。
先下载glove embeddings
wget http://nlp.stanford.edu/data/glove.6B.zip
然后运行下面的命令对GLUE数据集进行扩展
export TASK_NAME=SST-2
export GLOVE_EMB="glove/glove.6B.300d.txt"
python data_augmentation.py --pretrained_bert_model bert-base-uncased \
--glove_embs $GLOVE_EMB \
--glue_dir /root/.paddlenlp/datasets/Glue/ \
--task_name $TASK_NAME
运行结束后,在glue_dir/$TASK_NAME目录下,会生成train_aug.tsv
的数据增强后的训练集文件。
利用task_distill.py
时,带上--use_aug这个参数,程序会读取train_aug.tsv
作训练集进行训练。
经过实验,利用数据增强后的数据集,在RTE数据集上,Acc由0.7148提升至0.7184。
Jiao X, Yin Y, Shang L, et al. TinyBERT: Distilling BERT for Natural Language Understanding[J]. arXiv preprint arXiv:1909.10351v5, 2020.
黑客松task_55,在PaddleNLP的Roberta中,新增 MultipleChoice,MaskedLM 和 CausalLM三个类,7个模型权重. ,新增BPETokenizer
Python C++ Cuda Text Shell other
Dear OpenI User
Thank you for your continuous support to the Openl Qizhi Community AI Collaboration Platform. In order to protect your usage rights and ensure network security, we updated the Openl Qizhi Community AI Collaboration Platform Usage Agreement in January 2024. The updated agreement specifies that users are prohibited from using intranet penetration tools. After you click "Agree and continue", you can continue to use our services. Thank you for your cooperation and understanding.
For more agreement content, please refer to the《Openl Qizhi Community AI Collaboration Platform Usage Agreement》