引言
上一节介绍了 DistilBERT \text{DistilBERT} DistilBERT模型,本节将继续介绍优化性更强的知识蒸馏 BERT \text{BERT} BERT模型—— TinyBERT \text{TinyBERT} TinyBERT模型。
回顾:DistilBERT模型
DistilBERT \text{DistilBERT} DistilBERT模型是一种基于 BERT-base \text{BERT-base} BERT-base的知识蒸馏版本,其模型结构表示如下。单从模型结构的角度观察,学生模型神经元的维度没有发生变化 ( 768 ) (768) (768),仅是 Encoder \text{Encoder} Encoder层数减少为 BERT-base \text{BERT-base} BERT-base的一半;并且各层的初始化继承了一部分 BERT-base \text{BERT-base} BERT-base:从教师模型的 Encoder \text{Encoder} Encoder层中每两层选择一层作为学生模型 Encoder \text{Encoder} Encoder层的初始化。
DistilBERT \text{DistilBERT} DistilBERT训练出的学生模型( param:66M \text{param:66M} param:66M)依然可以达到 BERT-base \text{BERT-base} BERT-base模型几乎 97 97 97%的准确度。能够达到这个效果离不开 DistilBERT \text{DistilBERT} DistilBERT的三个核心策略:
- 掩码语言模型策略 ( Masked Language Model ) (\text{Masked Language Model}) (Masked Language Model):根据 RoBERTa \text{RoBERTa} RoBERTa中的描述,摒弃掉下句预测 ( Next Sentence Prediction,NSP ) (\text{Next Sentence Prediction,NSP}) (Next Sentence Prediction,NSP)策略,并使用动态掩码替代静态掩码作为 BERT \text{BERT} BERT模型的训练策略;
- 蒸馏策略 ( Distillation loss ) (\text{Distillation loss}) (Distillation loss):通过使用 Softmax \text{Softmax} Softmax温度函数将教师模型 BERT-base \text{BERT-base} BERT-base与学生模型 DistilBERT \text{DistilBERT} DistilBERT输出层的解空间尽可能地相似:
其中
N N N表示教师模型和学生模型的输出层维度,在
DistilBERT \text{DistilBERT} DistilBERT模型中,两者的维度相同,均为
768 768 768。
T ( x ) = ( t 1 , t 2 , ⋯ , t N ) S ( x ) = ( s 1 , s 2 , ⋯ , s N ) L c r o s s = − ∑ i = 1 N t i ∗ log ( s i ) \begin{aligned} & \mathcal T(x) = (t_1,t_2,\cdots,t_N) \\ & \mathcal S(x) = (s_1,s_2,\cdots,s_{N}) \\ & \mathcal L_{cross} = -\sum_{i=1}^{N} t_i * \log (s_i) \end{aligned} T(x)=(t1,t2,⋯,tN)S(x)=(s1,s2,⋯,sN)Lcross=−i=1∑Nti∗log(si) - 余弦嵌入策略 ( Cosine Embedding loss ) (\text{Cosine Embedding loss}) (Cosine Embedding loss):通过计算输出层分布向量之间夹角的余弦值 cos [ T ( x ) , S ( x ) ] \cos [\mathcal T(x),\mathcal S(x)] cos[T(x),S(x)],当该值为 1 1 1时,对应的 L c o s i n e \mathcal L_{cosine} Lcosine达到最小。此时两向量的方向为同一方向,教师和学生模型输出的解空间已被对齐:
L c o s i n e = 1 − cos [ T ( x ) , S ( x ) ] \mathcal L_{cosine} = 1 - \cos[\mathcal T(x),\mathcal S(x)] Lcosine=1−cos[T(x),S(x)]
总结:
在 ALBERT \text{ALBERT} ALBERT模型中介绍过,虽然 ALBERT \text{ALBERT} ALBERT也是 BERT \text{BERT} BERT的简化版本,但它们的解空间并不相同;
与此相反, DistilBERT \text{DistilBERT} DistilBERT中除了继承了 BERT \text{BERT} BERT中的掩码语言模型策略外,剩余的两条策略均是围绕牢牢绑定教师模型与学生模型的解空间而设计。
重新观察学生模型 DistilBERT \text{DistilBERT} DistilBERT,它能够达到如此精炼的模型结构 ( param:110M -> 66M ) (\text{param:110M -> 66M}) (param:110M -> 66M),但依然保持极高的准确性,没有出现欠拟合的情况。这至少意味着: DistilBERT \text{DistilBERT} DistilBERT模型中的神经元被利用得更加充分。
在这种情况下,是否可以百尺竿头更进一步呢 ? TinyBERT ?\text{ TinyBERT} ? TinyBERT模型给了我们一个更精进的答案。
TinyBERT_29">TinyBERT模型结构
相比于 DistilBERT \text{DistilBERT} DistilBERT模型中 Encoder \text{Encoder} Encoder层数减半的严肃操作, TinyBERT \text{TinyBERT} TinyBERT模型可以自定义学生模型的层数。并且还可以设置隐藏层单元中神经元的维度,从而使模型更加精简。那么它是如何实现在如此精简的模型结构下,不仅没有欠拟合,而且还能保持优秀的训练结果呢 ? ? ? 自然是依靠更加严苛的策略作为约束。
TinyBERT \text{TinyBERT} TinyBERT模型的教师-学生模型结构表示如下:
TinyBERT structure" />
其中索引 0 0 0表示嵌入层, 1 1 1表示第一个 Encoder \text{Encoder} Encoder,以此类推。最后 N+1,M+1 \text{N+1,M+1} N+1,M+1分别表示教师、学生模型的预测层。
该蒸馏结构与 DistilBERT \text{DistilBERT} DistilBERT之间没有太大区别,只不过没有 DistilBERT \text{DistilBERT} DistilBERT中的初始化操作。教师与学生模型中各层的迁移过程可以表示为如下式子:
n = G ( m ) n = \mathcal G(m) n=G(m)
其表达的含义是:将教师模型中的第 n n n层迁移到学生模型的第 m m m层。例如:
- 0 = G ( 0 ) 0 = \mathcal G(0) 0=G(0)表示将教师模型的嵌入层知识迁移到学生模型的嵌入层;
- N + 1 = G ( M + 1 ) N+1 = \mathcal G(M+1) N+1=G(M+1)表示将教师模型的预测层知识迁移到学生模型的预测层;
- n = G ( m ) n = \mathcal G(m) n=G(m)表示将教师模型的第 n n n个 Encoder \text{Encoder} Encoder层知识迁移到学生模型的第 m m m个 Encoder \text{Encoder} Encoder层。
TinyBERT_43">TinyBERT模型策略
那么 TinyBERT \text{TinyBERT} TinyBERT是如何制定策略的呢 ? ? ? 主要围绕三个部分制定策略:
- Transformer \text{Transformer} Transformer层 ( Encoder ) (\text{Encoder}) (Encoder)
- 嵌入层 ( Embedding Layer ) (\text{Embedding Layer}) (Embedding Layer)
- 预测层 ( Predict Layer ) (\text{Predict Layer}) (Predict Layer)
Transformer层蒸馏
在 Transformer \text{Transformer} Transformer层也就是编码器层,需要使用多头注意力机制计算注意力矩阵,再使用 FeedForward Network \text{FeedForward Network} FeedForward Network进行一个前馈计算,并将最终计算得到的隐藏状态特征作为该编码器的输出。在 TinyBERT \text{TinyBERT} TinyBERT中除了将教师模型中 Encoder \text{Encoder} Encoder内的注意力矩阵迁移到学生模型相应的 Encoder \text{Encoder} Encoder中,也同时将相应的隐藏状态特征迁移到学生模型中。因而 Transformer \text{Transformer} Transformer层蒸馏包括两次知识蒸馏:
- 基于注意力的蒸馏
通过最小化对应学生 Encoder \text{Encoder} Encoder和教师 Encoder \text{Encoder} Encoder内注意力矩阵的均方误差来训练对应学生 Encoder \text{Encoder} Encoder层:其中
h h h表示注意力机制头的数量;
A i S \mathcal A_i^{\mathcal S} AiS表示学生
Encoder \text{Encoder} Encoder内第
i i i个头的注意力矩阵;
A i T \mathcal A_i^{\mathcal T} AiT表示教师
Encoder \text{Encoder} Encoder内第
i i i个头的注意力矩阵;
MSE \text{MSE} MSE表示均方误差操作。
个人疑问:当学生模型隐藏层维度变化的时候
A i S , A i T \mathcal A_i^{\mathcal S},\mathcal A_i^{\mathcal T} AiS,AiT是一样大的吗?但书中并没有解释。
L a t t n = 1 h ∑ i = 1 h MSE ( A i S , A i T ) \mathcal L_{attn} = \frac{1}{h} \sum_{i=1}^{h} \text{MSE}(\mathcal A_i^{\mathcal S}, \mathcal A_i^{\mathcal T}) Lattn=h1i=1∑hMSE(AiS,AiT)
需要注意的是,这里的注意力矩阵 A i S , A i T \mathcal A_i^{\mathcal S},\mathcal A_i^{\mathcal T} AiS,AiT使用的是执行 Layer Norm \text{Layer Norm} Layer Norm映射前的矩阵,这样做的目的是保证信息的完整性,并且更快地收敛。
- 基于隐藏状态的蒸馏
隐藏状态是当前 Encoder \text{Encoder} Encoder的输出,我们同样需要将教师 Encoder \text{Encoder} Encoder的隐藏层知识迁移到学生 Encoder \text{Encoder} Encoder的隐藏层状态中:
其中
H S \mathcal H_{\mathcal S} HS表示学生
Encoder \text{Encoder} Encoder内的隐藏层状态;
H T \mathcal H_{\mathcal T} HT表示教师
Encoder \text{Encoder} Encoder内的隐藏层状态。同样使用均方误差使
H S \mathcal H_{\mathcal S} HS向
H T \mathcal H_{\mathcal T} HT方向拟合。
L h i d n = MSE ( H S , H T ) \mathcal L_{hidn} = \text{MSE}(\mathcal H_{\mathcal S},\mathcal H_{\mathcal T}) Lhidn=MSE(HS,HT)
但需要注意的是:当学生 Encoder \text{Encoder} Encoder隐藏层维度发生变化时, H S \mathcal H_{\mathcal S} HS和 H T \mathcal H_{\mathcal T} HT两者之间的维度之间存在差异,因而需要训练一个新的权重矩阵 W h \mathcal W_{h} Wh使两者处于同一级别的维度空间:
相当于作用在损失函数上的权重矩阵,反向传播过程中同样存在梯度更新。
L h i d n = MSE ( H S W h , H T ) \mathcal L_{hidn} = \text{MSE}(\mathcal H_{\mathcal S}\mathcal W_h, \mathcal H_{\mathcal T}) Lhidn=MSE(HSWh,HT)
嵌入层蒸馏
关于嵌入层的蒸馏与隐藏状态的蒸馏相似,当学生模型设置的隐藏层维度与教师模型维度不同时,两者对应的 Embedding \text{Embedding} Embedding也不同。同样在损失函数中添加一个新的权重参数 W E \mathcal W_{\mathcal E} WE,使两个 Embedding \text{Embedding} Embedding处于同一级别的维度空间:
其中
E S \mathcal E_{\mathcal S} ES表示学生模型的
Embedding \text{Embedding} Embedding矩阵;
E T \mathcal E_{\mathcal T} ET表示教师模型的
Embedding \text{Embedding} Embedding矩阵。
MSE \text{MSE} MSE表示均方误差。
L e m b = MSE ( E S W E , E T ) \mathcal L_{emb} = \text{MSE}(\mathcal E_{\mathcal S} \mathcal W_{\mathcal E} ,\mathcal E_{\mathcal T}) Lemb=MSE(ESWE,ET)
预测层蒸馏
在预测层蒸馏部分,迁移的是输出层的知识信息。这里和 DistilBERT \text{DistilBERT} DistilBERT模型关于预测层的损失类似。对于教师模型的输出 Z T \mathcal Z^{\mathcal T} ZT和学生模型的输出 Z S \mathcal Z^{\mathcal S} ZS:
- 使用 Softmax \text{Softmax} Softmax温度函数分别获取对应的软目标 P T \mathcal P^{\mathcal T} PT和软预测 P S \mathcal P^{\mathcal S} PS结果:
同理,
Z T \mathcal Z^{\mathcal T} ZT对应的软目标结果
P T \mathcal P^{\mathcal T} PT不再赘述。
{ P i S = exp ( Z i S / T ) ∑ j exp ( Z j S ) / T P S = ( P 1 S , P 2 S , ⋯ , P N S ) \begin{cases} \begin{aligned} \mathcal P_{i}^{\mathcal S} = \frac{\exp(\mathcal Z_i^{\mathcal S} / \mathcal T)}{\sum_{j} \exp(\mathcal Z_j^{\mathcal S}) / \mathcal T} \end{aligned} \\ \quad \\ \mathcal P^{\mathcal S} = (\mathcal P_1^{\mathcal S},\mathcal P_{2}^{\mathcal S},\cdots,\mathcal P_{N}^{\mathcal S}) \end{cases} ⎩ ⎨ ⎧PiS=∑jexp(ZjS)/Texp(ZiS/T)PS=(P1S,P2S,⋯,PNS) - 再使用交叉熵损失函数对 P S \mathcal P^{\mathcal S} PS与 P T \mathcal P^{\mathcal T} PT进行描述:
L p r e d = − P T ⋅ log ( P S ) \mathcal L_{pred} = - \mathcal P^{\mathcal T} \cdot \log \left(\mathcal P^{\mathcal S} \right) Lpred=−PT⋅log(PS)
最终, TinyBERT \text{TinyBERT} TinyBERT包含所有层的损失函数表示如下:
这里
[ S m , T G ( m ) ] [\mathcal S_{m},\mathcal T_{\mathcal G(m)}] [Sm,TG(m)]表示学生模型的第
m m m层与教师模型第
G ( m ) \mathcal G(m) G(m)之间的迁移关系。
L [ S m , T G ( m ) ] = { L e m b ( S 0 , T 0 ) m = 0 L h i d n ( S m , T G ( m ) ) M ≥ m > 0 L p r e d ( S M + 1 , T N + 1 ) m = M + 1 \mathcal L \left[ \mathcal S_{m},\mathcal T_{\mathcal G(m)}\right]= \begin{cases} \mathcal L_{emb}(\mathcal S_0,\mathcal T_0) \quad m = 0 \\ \mathcal L_{hidn}(\mathcal S_m,\mathcal T_{\mathcal G(m)}) \quad M \geq m > 0 \\ \mathcal L_{pred} (\mathcal S_{M+1},\mathcal T_{N+1}) \quad m = M + 1 \end{cases} L[Sm,TG(m)]=⎩ ⎨ ⎧Lemb(S0,T0)m=0Lhidn(Sm,TG(m))M≥m>0Lpred(SM+1,TN+1)m=M+1
可以看出:
- TinyBERT \text{TinyBERT} TinyBERT损失函数数量是不确定的。它取决于设计学生模型 ( TinyBERT ) (\text{TinyBERT}) (TinyBERT)的层的数量;
- 相比于 DistilBERT \text{DistilBERT} DistilBERT, TinyBERT \text{TinyBERT} TinyBERT需要为削减隐藏层状态维度和层数付出相应的代价——设计的策略需要与教师模型关系更加紧密,并精确到注意力矩阵和隐藏层状态,从而得到一个与教师模型关联更加紧密的、学生模型的解空间。
TinyBERT_96">TinyBERT模型的训练
在文章中作者描述的训练流程表示如下:
在 TinyBERT \text{TinyBERT} TinyBERT模型中,使用两个阶段进行训练:
- 通用蒸馏:在该阶段,使用 BERT-base \text{BERT-base} BERT-base预训练模型作为教师,并使用 BERT-base \text{BERT-base} BERT-base的训练集对学生模型 ( TinyBERT ) (\text{TinyBERT}) (TinyBERT)进行蒸馏。并将该模型称作通用 TinyBERT \text{TinyBERT} TinyBERT模型。
- 特定任务蒸馏:在微调阶段,将基于一项具体任务对通用 TinyBERT \text{TinyBERT} TinyBERT模型进行微调 ( fine-tuning ) (\text{fine-tuning}) (fine-tuning)。具体微调过程方式为:
效果展示
论文中关于 TinyBERT \text{TinyBERT} TinyBERT对于各下游任务中,与各模型比较结果如下:
其中, DistilBERT 4 \text{DistilBERT}_4 DistilBERT4表示学生模型包含 4 4 4层 Encoder \text{Encoder} Encoder,其他同理。可以发现:
- 相比于 DistilBERT 4 \text{DistilBERT}_4 DistilBERT4, TinyBERT 4 \text{TinyBERT}_4 TinyBERT4使用不到其 30 30 30%,但准确率却远高于 DistilBERT \text{DistilBERT} DistilBERT模型;
- TinyBERT 6 \text{TinyBERT}_6 TinyBERT6参数数量是 BERT-base \text{BERT-base} BERT-base的 60 60 60%左右,但其准确性基本与 BERT-base \text{BERT-base} BERT-base持平。
Reference \text{Reference} Reference:
论文链接
《BERT基础教程——Transformer大模型实战》