11月主要论文整理
最近刚写完毕设和实习复现论文的工作,打算浏览下近期的预训练语言模型的论文(毕设里简单介绍了下这个的思想,并且以后工作了可能会做相关的工作,所以在这学习下)。我们可以以Glue
榜单来check下最近的预训练语言模型的论文。据目前所知的情况来看,可以分为几个部分:
- 修改bert的模型:参数量|本身框架
- 修改预训练目标
- 添加一些先验知识
2019-11-18
修改bert模型
出发点:目前的预训练模型参数量太大,降低模型参数量
贡献:设计了两种减少参数量的技术,设计了一个自监督损失来建模句内共现,有利于多句输入的下游任务
摘要:
- 作者发现:训练步不够时bert模型性能不佳,增倍bert-large的hidden_size性能也不佳(why?)
- 要设计一个模型:address the memory limitation problem, the communication overhead
- and model degradation,也就是说既要降低参数量又要保证模型不退化,所 以设计了模型ALBERT(A Lite BERT)
模型:
- factorized embedding parameterization:把词表的embedding matrix分解为两个子矩阵
- cross-layer parameter sharing:随着网络加深保留参数->意思就是底层的参数给上层共享,也就是多层共享一个参数,而不是每层都是一个新参数(所有层只有一组参数?)->这边会有一个问题:虽然参数量变小了,但是其实本质上速度没有变,还是迭代了同样N次
- SOP: sentence-order prediction:改进NSP
details:
对于wordpiece embedding学习的是context-independent表示(和词向量一样,与上下文无关),
而hidden-layer embedding则学的是context-dependent表示。所以,因为要更需要学到的是上下文相关的表示,这也是为什么H>>E的原因,原有的模型的词向量矩阵是$V \times E$。所以该方法就是先将词表映射到低维向量,再从低维升到hidden_size,则参数量则从$O(V\times H)$到$O(V \times E+ E \times H)$,当H>>E时参数量会大幅度减少。那么我们的E要设多大呢?在
ALBERTZ中是设为128。跨层的参数共享:可以共享FFN,也可以共享attention parameters,ALBERT的选择是共享所有参数
Inter-sentence coherence loss:使用SOPloss来实现,正例和NSP中一样生成,而负例则用同样相邻的两个片段但是它们的顺序调换。
实验结果:还是很牛逼的,参数量降低了10倍和base版的bert效果差不多,通过增大H的大小,能够达到更好的效果。在Squad上,(xlarge(ALBERT)60M->bert_large(334M))
- 具体实现上:(参考transformers中的albert实现):在模型部分主要要改动两个部分
- 改动原有的embedding layers的输入输出大小
1 | class AlbertEmbeddings(nn.Module): |
在transformer输入前转为hidden_size
1 | class AlbertEncoder(nn.Module): |
- 共享所有跨层的参数:对应self-attention+FFN迭代N次(layer numbers),现在只用一组参数
来共享
1 | class AlbertTransformer(nn.Module): |
预训练任务 or 增强训
先验知识
2019-11-20
主要是bert模型压缩的问题,从alberta中我们可以
知道一部分模型压缩的方式。有几个技术分享:
All The Ways You Can Compress BERT
结合以上,主要的方法有权重分解(like 上面讲的alberta),知识蒸馏,权重分享,剪纸,混合精度(fp16之类的)。今天我们check一下知识蒸馏。
知识蒸馏:就是用到teacher+student的思想,利用student模型来拟合teacher的输出分布,
框架如图所示:
可以看到,主要是通过输出类别的概率来计算loss,在pytorch中可以使用KLD散度loss来等价计算软标签的交叉熵。(参考BERT瘦身之路)
1 | loss = nn.KLDivLoss(F.log_softmax(s_logits/temperature),F.softmax(t_logits/temperature)) # temperature保存分布平滑 |
那我们来看看DistillBERT模型。这个模型压缩了bert的40%的大小,保留了97%的性能和加速了60%的速度。在8个16GB的V100上训了90个小时,这种蒸馏的方式相当只更新student部分的参数,所以才能达到这么快的速度。
可以看hf的博客文章Smaller, faster, cheaper, lighter: Introducing DistilBERT, a distilled version of BERT。
核心点在于”We are trainning the student to generalize the same way
as the teacher by matching the output distribution.”
训练损失如下:
其中$t$是从teacher model中预测的logits,而$s$则是从student中预测的。
接着引入softmax-temperature做平滑:
当T趋向0,则满足Kronecker分布,而趋向无穷大时,则成uniform分布。
在训练的时候在s和t中都设置T使得能从训练样本中学习到更多信号,而预测时则设置
T=1。
在具体实现中使用KL损失:
可以在pytorch中实现这个过程
1 | import torch |
整个项目的具体实现可以参考code
混合精度加速
混合精度的训练主要流程是在模型训练过程中使用FP16加速计算过程,而
模型训练的过程中权重会存储成FP32格式,参数更新的时候则采用FP32类型。