随着计算算力的不断增加,以transformer为主要架构的预训练模型进入了百花齐放的时代。BERT、RoBERTa等模型的提出为NLP相关问题的解决提供了极大的便利,但也引发了一些新的问题。首先这些经过海量数据训练的模型相比于一般的深度模型而言,包含更多的参数,动辄数十亿。在针对不同下游任务做微调时,存储和训练这种大模型是十分昂贵且耗时的。尤其对于机器翻译任务而言,如果针对一对语言对就需要存储和微调这样一个”庞然大物“,显然在时间和空间上都是不可接受的。
为了解决这个问题,以轻量和扩展性强闻名的Adapter方法被提出,相比于“劳民伤财”的全参数微调,它只需要以一个较小的训练和存储代价就可以取得和全模型微调相当的结果。
Adapter方法介绍
首先adapter方法的原理并不复杂,它是通过在原始的预训练模型中的每个transformer block中加入一些参数可训练的模块实现的。
假设原始的预训练模型的参数为ω,加入的adapter 参数为υ,在针对不同下游任务进行调整时,只需要将预训练参数固定住,只针对adapter参数υ进行训练。通常情况下,参数量υ<<ω, 因此在对多个下游任务调整时,只需要调整极小数量的参数,大大的提高了预训练模型的扩展性和实用性。对于adapter模块的网络组成,不同文章中针对不同任务略有不同。但是比较一致的结论是,bottleneck形式的两层全连接神经网络就已经可以满足要求。
在Houlsby[1]的文章中,每个transformer 层中有两个adapter模块,在每个adapter模块中,先将经过多头注意力和前馈层输出的output做一个降维的映射。经过一个非线性激活层后,再将特征矢量映射回原始的维度。在下游训练任务中,只更新adapter模块和layer Norm 层(图一中的绿色部分)。
相比于预训练模型的全参数微调,Adapter 方法的优势十分明显:
(1)针对不同下游任务可保持预训练模型不变,仅需训练adapter模块的少量参数,训练代价小,可移植性强。
(2)对于不同任务的连续学习(continual learning)而言,由于在训练不同任务时只需要训练不同的adapter,其他模型参数保持不变,避免了在学习新任务时对过往任务的遗忘。
adapter开源库
链接:>>Click me<<
使用示例:
Fine-tuing AdapterHub_00_Full_Finetuning.ipynb
Adapter AdapterHub_01_Adapter_Training.ipynb
huggingface 开源的transformer 库十分的方便易用,各种SOTA的BERT、RoBERTa预训练模型应有尽有。更贴心的是,他们在原来框架的基础上增添了adapter 模块的训练和扩展——AdapterHub,用户只需要在原来的训练脚本中更改不超过两行的代码,就可以针对不同的下游任务无缝训练新的adapter模块,并且整个adapter模块的参数和原始的预训练模型参数是完全独立存储的。
此外,该库的另一大特点就是完全开源与共享,如下图所示,每个用户都可以基于huggingface提供的预训练模型训练并上传自己的adapter模块,而其他用户也可以根据个人的任务选择对应的预训练adapter模块直接使用。