知识蒸馏 - Teacher与Student爱恨情仇
这是一篇自己读知识蒸馏(knowledge distillation, KD)的一些论文的笔记。为了帮助自己记忆与理解,举了一些例子。
若有不准确或者不恰当,欢迎批评指教。
以下主要内容来自以下论文:
[1] Hinton G, Vinyals O, Dean J. Distilling the knowledge in a neural network[J]. arXiv preprint arXiv:1503.02531, 2015.
[2] Cho J H, Hariharan B. On the Efficacy of Knowledge Distillation[C] ICCV. 2019.
[3] Mirzadeh S I, Farajtabar M, Li A, et al. Improved knowledge distillation via teacher assistant: Bridging the gap between student and teacher[J]. arXiv preprint arXiv:1902.03393, 2019.(Washington State University && DeepMind)
赶时间的同学可以直接跳到 第4部分-总结 看结论。
目录
知识蒸馏 - Teacher与Student爱恨情仇
1. 知识蒸馏的简介
1.1 背景
1.2 Teacher模型中的知识是什么呢?
1.3 Teacher如何把自己的知识“教”给Student呢?
1.4 知识蒸馏
1.5 实验及实验结论
1.5.1 **知识蒸馏在MNIST手写数字分类任务**
1.5.2 **知识蒸馏在语音识别上的实验**
2. 学富五车的“Teacher”就能够教出好“Student”吗?
2.1 Teacher模型并非越复杂越准确越好
2.2 WHY?
2.3 如何减缓这个现象 —— Early Stop
提早停止的Teacher是一个好Teacher
3 学霸好好学习,学渣需要帮助 —— 助教
3.1 “助教”实验
3.2 “助教”最好是什么样的水平?
3.2 并不局限只有一个助教
4. 总结
1. 知识蒸馏的简介
1.1 背景
在大规模的机器学习中,我们通常在训练阶段和部署阶段使用非常相似的模型,即使两个阶段各自有各自的要求。
训练阶段并不要求实时性,但是需要从大量高冗余的数据集中抽取出有效的结构,这需要复杂模型来完成,复杂模型可以是多个独立的模型的集成,也可以是使用某种强正则化训练的单个大型模型。
在面对海量用户的部署阶段,对延时和计算资源有更高的要求,这是复杂模型所不能完成的。然而当复杂模型训练完成时,我们可以额外进行一种叫“蒸馏”的训练,将知识从复杂模型转移到更适合部署的小模型上。
既然是知识的转移,在知识蒸馏中,有一个很形象的比喻,就是训练阶段得到的模型把知识“教”给蒸馏后的模型。这样,我们把训练阶段得到的模型称为教师模型(Teacher),把蒸馏的目标模型称为学生模型(Student)。
1.2 Teacher模型中的知识是什么呢?
两种说法:
模型中的参数,以及各个值的组合方式(即把每一个部分拆开,了解其中的含义,推导出最终的结果)
模型从输入向量到到输出向量的映射能力(即知识是一个黑盒子,只关心输入向量通过该模型的后的映射结果)
举一个例子,下表展示了三句网络用语“nsdd”,“y1s1”,“zqsg”,这三个词语普通不太常上微博的朋友,很难第一反应出这些短语的意思,然而经过别人的解释,通过一个一个的拆解,例如第一个“nsdd”,“n”是 “你”的意思,“s”是说的意思,第一个“d”和第二个“d”分别是“的”和“对”的意思,这是一个发音首字母的缩写,完整表达的意思是“你说的对”。这种理解的方式,就类似于上面的第一种说法,知道参数以及各个值的组合方式。然而,常上微博的朋友,可能对这些缩写非常熟悉,他们看到这些缩写,并不需要在脑中经过上面的“拆文解字”的过程,而可以直接反映出这个缩写的意思。这种方式更接近于上面提到的第二种说法。
两种说法的过程不同,最终映射出的结果相同,但是过程相差较大。但是由于深度学习的模型,虽然在结构上有一定的可解释性,但是其内部参数的可解释性依然不好,所以在知识蒸馏中,采用的是第二种说法,知识是模型从输入输入向量到输出向量的的映射的能力。
网络用语 说法1 说法2
nsdd (n:你,s:说,d:的,d:对) → \rightarrow → 你说的对 nsdd → \rightarrow → 你说的对
y1s1 (y:有,1:一,s:说,1:一) → \rightarrow → 有一说一 y1s1 → \rightarrow → 有一说一
zqsg (z:真,q:情,s:时,g:感) → \rightarrow → 真情实感 zqsg → \rightarrow → 真情实感
1.3 Teacher如何把自己的知识“教”给Student呢?
举一个例子,假设一个任务是识别图片中的任务是否是“皮卡丘”,是皮卡丘,表示为(1, 0), 不是皮卡丘表示为(0, 1):
在这里插入图片描述
图1 图片分类样例示意图
假设我们的模型已经训练完成。
依据前面的说法,知识是从输入向量到输出向量映射的能力。对于老师和学生来说,他们的输入自然是相同的,都是这些图片,那么输出是什么呢?首先想到的,最满意的输出自然就是他们的标签了(如果模型最后能直接输出真实的标签,那真实太好了)。以上面四幅图为例,我们来看一看他们的标签。前两张图是皮卡丘,后两张图不是皮卡丘,所以图(1) - 图(4)的标签如下:
( 1 ) [ 1 , 0 ] ( 2 ) [ 1 , 0 ] ( 3 ) [ 0 , 1 ] ( 4 ) [ 0 , 1 ] (1)\ \ \ \ [1, 0]\ \ \ \ (2)\ \ \ \ [1, 0]\ \ \ \ (3)\ \ \ \ [0, 1]\ \ \ \ (4)\ \ \ \ [0, 1] (1) [1,0] (2) [1,0] (3) [0,1] (4) [0,1]
这些标签传达了哪些信息呢?这些标签仅传达了“是”与“不是”的信息。这个标签信息所包含的知识,远远不够。
我们从图(1)和图(2)中可以看出,图(1)是一个常态的皮卡丘,而图(2)是一个做鬼脸的皮卡丘,图(2)中皮卡丘的脸的形状都有改变,如果换一个不熟悉皮卡丘的人,说不定都不能判定图(2)是皮卡丘。图(3)和图(4)分别是皮丘和杰尼龟,这两幅图都不是皮卡丘,但是皮丘与皮卡丘一样有有两个红脸颊,且身体也是黄色的,其他地方也多多少少类似于皮卡丘,杰尼龟与皮卡丘的外貌完全不同,那么图(3)皮丘与图(4)杰尼龟相比,虽然都不是皮卡丘,但是皮丘与皮卡丘更接近。
那么Teacher模型如何能把我们上面描述的信息表达出来呢?我们把Teacher模型从标签输出的地方往前倒车一层,来到了概率层,即如果一个训练阶段的模型训练恰当,那么它对以上四幅图片的输出会有以下的情况:(数值仅为举例用)
( 1 ) [ 0.9999 , 0.0001 ] ( 2 ) [ 0.8975 , 0.1025 ] ( 3 ) [ 0.4131 , 0.5869 ] ( 4 ) [ 0.0002 , 0.9998 ] (1)\ \ \ \ [0.9999, 0.0001]\ \ \ \ (2)\ \ \ \ [0.8975, 0.1025]\ \ \ \ (3)\ \ \ \ [0.4131, 0.5869]\ \ \ \ (4)\ \ \ \ [0.0002, 0.9998] (1) [0.9999,0.0001] (2) [0.8975,0.1025] (3) [0.4131,0.5869] (4) [0.0002,0.9998]
这个Teacher模型输出的概率,就能够表达我们上面提到的信息。图(1)和图(2)都是皮卡丘(图(1)和图(2)第一维都比第二维大),但是图(1)相比于图(2)更接近于平常的皮卡丘(图(1)第一维的概率大于图(2)第一维的概率);图(3)和图(4)都不是皮卡丘(图(3)和图(4)的第一维都小于第二维),但是皮丘比杰尼龟更像皮卡丘(图(3)第二维的概率大于图(4)第二维的概率)。
我们称呼图片直接的标签信息为硬目标(hard target),而这种概率信息为软目标(soft target)。那么软目标可以相比于硬目标不仅包含“是”与“不是”的信息,还包含图片之间“谁更像”与“谁更不像”的信息,所以我们的直接就是,将Teacher模型输出的概率,作为数据的标签,送到Student模型进行训练。
1.4 知识蒸馏
以分类任务为例,依照上面的叙述,Teacher模型训练的损失函数为普通的交叉熵函数(即以硬目标为标签) L o s s T e a c h e r = − ( y 1 ⋅ l o g ( p 1 ^ ) + y 2 ⋅ l o g ( p 2 ^ ) ) Loss_{Teacher} = -(y_1 \cdot log(\hat{p_1}) + y_2 \cdot log(\hat{p_2})) LossTeacher=−(y1⋅log(p1^)+y2⋅log(p2^))
Student模型的的损失函数为 L o s s S t u d e n t = − ( p 1 ⋅ l o g ( q 1 ^ ) + p 2 ⋅ l o g ( q 2 ^ ) ) Loss_{Student} = -(p_1 \cdot log(\hat{q_1}) + p_2 \cdot log(\hat{q_2})) LossStudent=−(p1⋅log(q1^)+p2⋅log(q2^))
其中 y 1 y_1 y1和 y 2 y_2 y2分别是硬目标第一维和第二维的值, p 1 p_1 p1和 p 2 p_2 p2分别是Teacher模型概率输出第一维和第二维的值,同时也是Student模型软目标第一维和第二维的值, q 1 ^ \hat{q_1} q1^和 q 2 ^ \hat{q_2} q2^分别是Student模型概率输出第一维和第二维的值.
但是在实际操作中如果这么做,有一个弊端。如果Teacher模型足够大,且训练充分,那么它大多数输出,都类似于上面图(1)和(4)的输出 [ 0.9999 , 0.0001 ] [0.9999, 0.0001] [0.9999,0.0001]和 [ 0.0002 , 0.9998 ] [0.0002, 0.9998] [0.0002,0.9998],概率输出(软目标)会极大地往某一个维度上偏。这使得Student的目标函数会极易受到某一个维度的影响,而其他的维度几乎不影响该目标函数,这个影响在维度更高时的影响会更大。
解决方法(1):Caruana等人从模型概率输出的地方,再往前倒车一层,取用对softmax层输入logits作为软目标。
解决方法(2):引入一个超参数T,命名为“温度”,将softmax层的计算修改为 q i = e x p ( z i / T ) ∑ j e x p ( z j / T ) q_i=\frac{exp(z_i/T)}{\sum_j{exp(z_j/T)}} qi=∑jexp(zj/T)exp(zi/T)这正是知识蒸馏所使用的方法。这么做,可以在保留软目标相对标签的大小时,减缓输出概率往某一个维度偏的现象。
在知识蒸馏的过程中,训练Teacher模型和训练Student模型的时候,温度T需要设定的相同。但在Student模型进行预测时,需要将T恢复为1,即最后的概率输出需要恢复为原始的softmax。
那么,方法(1)与方法(2)有什么不同呢?论文[1]从数学上证明了解决方法(1)是方法(2)的一个特例,所以方法(2)是一个更加通用的解决方法。
**论文[1]还给出一个有趣的实验现象:Student模型在训练时,同时使用硬目标和软目标函数作为损失函数,但是硬目标函数的权重相比之下considerable lower。**关于这一点我的理解是:Teacher模型也会有识别错误的时候,如果仅仅使用Teacher所得出的软目标,那么这些错误将无法修复。但是如果在训练Student模型的过程中引入一小部分的硬目标信息,那么就是告诉模型,虽然Teacher模型这么输出,但是这是错误的,Student模型会进行进一步的修正。(这一点仅是个人的理解,若有错误,欢迎指出)
1.5 实验及实验结论
先上实验结论
编号 实验结论
1 通过知识蒸馏,可以将Teacher模型中的知识转移到Student模型,这样得到的Student模型要比直接训练的训练的相同模型有更好的泛化效果
2 如果复杂模型(Teacher)是一个集成模型,它组合了多个基模型,那么通过蒸馏Teacher训练得到的单个基模型,相比于直接训练的单个基模型有更好的泛化效果
1.5.1 知识蒸馏在MNIST手写数字分类任务
实验(1)
实验设置
实验组:Teacher模型:2层,宽1200的全连接网络;Student模型:2层,宽800的全连接网络。先训练Teacher模型,然后通过知识蒸馏的方式训练Student模型。
对照组:使用原始训练数据直接训练一个与实验组 Student模型相同的模型。
实验结果:在测试集上,Teacher模型有67个测试错误,对照组的模型有146个错误,而实验组的Student模型只有74个错误 。
实验(2)
实验设置 删除迁移集中的数字“3”,让Student在整个蒸馏过程中从未见过数字“3”
实验结果:蒸馏后的模型一共有206个测试错误,其中133个在数字“3”上(一共1010个);增大数字“3”这一类的bias大小后,蒸馏后的模型仅有109个测试错误,其中只有14个在数字“3”类上。
实验结论
通过知识蒸馏,可以将Teacher模型中的知识转移到Student模型,这样得到的Student模型要比直接训练的训练的相同模型有更好的泛化效果 。
1.5.2 知识蒸馏在语音识别上的实验
实验设置:
第一组(Baseline):8层,每一层包含2560个单元,最后接一个softmax层,一共14000个labels
第二组(10xEnsemble):训练10个第一组的模型,做成集成的大模型
第三组(Distilled Single Model):通过蒸馏训练的结构同第一组相同的模型
实验结果:
表1 知识蒸馏在语音识别上的实验的实验结果
System Test Frame Accuracy Word Error Rate
Baseline 58.9% 10.9%
10xEnsemble 61.1% 10.7%
Distilled Single Model 60.8% 10.7%
实验结论:
如果复杂模型(Teacher)是一个集成模型,它组合了多个基模型,那么通过蒸馏Teacher训练得到的单个基模型,相比于直接训练的单个基模型有更好的泛化效果
2. 学富五车的“Teacher”就能够教出好“Student”吗?
Intuition:根据我们的直觉,Teacher模型如果能更加准确(一般大模型能够带来更高的准确率),那么它“教”出来的Student也会更准确。但是下面的两个的实验反驳了这个观点。
2.1 Teacher模型并非越复杂越准确越好
图2来自于论文[2]:图2中左右两幅子图均为在CIFAR10数据集上的实验,左图为随着Teacher模型(WideResNet,WRN)深度的加深,Student模型WRN16-1与Student模型DN40-1的错误率;右图为随着Teacher模型宽度的加宽,Student模型WRN16-1与Student模型WRN28-1的错误率。
但是,从上面的实验看,随着Teacher模型变得更加复杂,但是它的“Student”的错误率并没有成一个下降的趋势。
图2 在CIFAR10数据集的Teacher模型尺寸实验结果
第2个实验使用ResNet模型在ImageNet数据集,一共四组实验:第一组为直接训练ResNet18模型,第二到第四组,分别使用ResNet18,ResNet34,ResNet50和ResNet152作为Teacher模型,ResNet18作为Student。实验结果见表1:随着Teacher模型的结构变得越复杂,Teacher模型的错误率在逐渐降低,然而Student模型的错误率却在逐渐增加(表中并未展示ResNet152的结果)
表2 在ImageNet数据集的改变Teacher模型尺寸实验结果
Teacher Teacher Error(%) Student Error(%)
- - 30.24
ResNet18 30.24 30.57
ResNet34 26.70 30.79
ResNet50 23.85 30.95
2.2 WHY?
为什么更加准确的Teacher模型,蒸馏出的Student模型并不是更加准确呢?两个猜想:
(1) Student其实是可以模仿Teacher,但是这并不能提升准确率。(意味着使用的蒸馏的loss函数与我们看重的准确率指标并不匹配)
(2) Student不能模仿Teacher。(意味着Student和Teacher之间容量的不匹配)
表3中实验结果显示了(另外还有一组在ImageNet上的实验,可见论文[2])两个结果。
随着Teacher模型结构变得复杂,其测试的KD Error(即蒸馏目标函数中的soft label部分)也变得越来越大,这也导致了其Student模型的准确率最低。(即知识传过去了,但是Student模型没有学到,Studnet的容量不足以支撑其学完知识)。这个现象正好验证了猜想(2)。
表3 在CIFAR10上比较知识蒸馏的Teacher和Student的KD错误率
Student Teacher KD Error(%, Train) KD Error(%, Test)
WRN28-1 WRN28-3 0.23 4.05
WRN28-4 0.25 4.53
WRN28-6 0.23 4.54
WRN28-8 0.31 4.81
WRN16-1 WRN16-3 1.70 6.32
WRN16-4 1.69 6.52
WRN16-6 1.94 6.91
WRN16-8 1.69 7.01
2.3 如何减缓这个现象 —— Early Stop
我们发现,虽然KD的缺失在一开始提高了验证集的准确,但在训练的最后阶段却开始影响准确。
我们假设任务是一个很难的任务,低容量的student模型处于欠拟合状态。它并没有足够的容量去同时降低训练loss和KD loss,所以训练后期需要牺牲一个loss去最小化另一个loss。根据这个假设,我们需要在蒸馏过程中提前停止KD(ES KD),后半阶段尽在普通的cross entropy上进行梯度下降。
表4比较了标准的知识蒸馏(Full KD)和提前停止的知识蒸馏(ES KD)。我们发现,ES KD的版本在三组实验中,均优于标准的知识蒸馏。而且ES KD的结果,相比于直接训练的30.24%的结果(表2),也印证了我们1.5.1中的结论 —— 通过知识蒸馏,可以将Teacher模型中的知识转移到Student模型,这样得到的Student模型要比直接训练的训练的相同模型有更好的泛化效果。
但是,注意到这里使用的词语是“减缓”,而不是解决,是因为Early Stop并没有解决我们2.1提出的问题。我们观察表4仍然可以发现,即便是在ES KD的版本下,随着Teacher模型越来越复发,其Student的模型的错误率仍然在上升。
表4 提早结束之时蒸馏可以有效减缓Student的分类效果下降
Teacher Top-1 Error(hi %, Test) CE(Train) KD(Train) KD(Test)
ResNet18 30.57 0.146 2.916 3.358
ResNet18(ES KD) 29.01 0.123 2.234 2.491
ResNet34 30.79 0.145 1.357 1.503
ResNet34(ES KD) 29.16 0.123 2.359 2.582
ResNet50 30.95 0.146 1.553 1.721
ResNet50(ES KD) 29.35 0.124 2.659 2.940
提早停止的Teacher是一个好Teacher
我们可以执行网格搜索来找到最优的老师,但是这样做费时费力。所以我们需要在训练时对Teacher模型加入一个正则化。特别的,我们提出要提前结束整个训练过程。虽然仅训练了一些epochs的大网络,会表现得像小网络一样,但是相比于小网络也会包含更大的搜索空间。这个方法相当的简单和方便,仅仅需要训练全epochs的1/4到1/3。(论文[2]在实验中还可以规划一下学习率,随着训练的进行逐渐减小)。(具体数据可在论文[2]中查看)
3 学霸好好学习,学渣需要帮助 —— 助教
上文也提到,如果Teacher模型与Student模型之间的容量不匹配,那么越准确的老师交出的学生也不会更聪明。从另一个角度来看,Student的模型存在极限,通俗来讲就是,不要让一个只会计算加减乘除的小学生马上去理解需要微积分才能理解的知识。当然不是表示这个知识它一定学不会,而是需要另一种讲解。
例如,我们小学的时候学习圆的面积,学的都是圆的面积是半径平方的π倍,而不是什么建立坐标系,根据圆方程求关系,再无限等分…积分…bla bla bla bla…
所以,在大的Teacher模型和小的Student模型之间,引入一个助教(TA)模型,将这个复杂的知识“简化”一点,是否就可以提升Student的泛化能力了呢?
3.1 “助教”实验
表5 “助教”模型的Accuracy对比实验(NOKD-无知识蒸馏,BLKD-基础知识蒸馏,TAKD-带助教的知识蒸馏)
Model Dataset NOKD BLKD TAKD
CNN CIFAR-10 70.16 72.57 73.51
CIFAR-100 41.09 44.57 44.92
ResNet CTFAR-10 88.52 88.65 88.98
CIFAR-100 61.37 61.41 61.82
ResNet ImageNet 65.20 66.60 67.36
表5中的结果,从三组结果都很明显的可以看出Student模型的准确率从NOKD,BLKD再到TAKD逐渐提升。
3.2 “助教”最好是什么样的水平?
先说实验结论:准确率在最好在Teacher准确率和Student准确率的均值水平上TA是最好的TA。打个比喻就是助教最好是老师和学生之间的中间水品。若助教的水平和老师跟接近,老师方便传授给助教知识,但是助教接受的知识缺不容易交给学生;相反若助教的水平更接近学生,那么助教教的学生能学,但是助教本身没有学到老师的精髓,所以自然也教不给学生。(这个比喻仅个人理解,若不恰当欢迎指出)
以下是实验结果:
表6 “助教”模型的大小不同,学生模型的Accuracy对比实验(T=10, S=2)
Model DataSet TA=8 TA=6 TA=4
CNN CIFAR-10 72.75 73.15 73.51
CNN CIFAR-100 44.28 44.57 44.92
表7 “助教”模型的大小不同,学生模型的Accuracy对比实验(T=110, S=8)
Model DataSet TA=56 TA=32 TA=20 TA=14
ResNet CIFAR-10 88.70 88.73 88.90 88.98
ResNet CIFAR-100 61.47 61.55 61.82 61.5
表6中最优秀“助教”是TA=4,表7中最优秀的“助教”是TA=14,而并非老师和学生模型尺寸的均值。把学生和老师直接训练的结果加入,我们可以看到下图3。其中红色额虚线表示Teacher模型和Student模型Accuracy的均值,可以看见CNN模型在CIFAR-10上,TA=4的效果相比于TA=6更接近于均值线,CNN模型在CIFAR-100上,TA=4的效果相比于TA=6也更接近于均值线。同样的结果在©(d)两幅子图也可以看到,所以可以得出上面的实验结论:准确率在最好在Teacher准确率和Student准确率的均值水平上TA是最好的TA。
在这里插入图片描述
图3 助教大小实验学生Accuracy对比图
3.2 并不局限只有一个助教
在Student和Teacher中间,可以有多个助教,即中间可以蒸馏多次。先看结果:
在这里插入图片描述
图4 不同蒸馏路径下学生模型的Accuracy
从上图4中,我们可以得到以下实验结论:
无论Student的大小是多少,TAKD的结果总是优于NOKD和BLKD
对比每一个数列,最后一行的NOKD策略的Student模型的效果总是最差的。
当Student的size为2时,无论什么路径,其效果都优于NOKD和BLKD。
当Student的size为2或4时,总是路径最长的 Student模型达到了最好的效果
4. 总结
知识蒸馏的目的是为了缩小模型,使其更适宜部署环境
知识蒸馏的知识是从输入向量映射出的输出向量,而非如何映射
知识蒸馏的做法是:在训练Teacher模型时,在softmax层引入一个温度T,在训练Student模型时,使用相同的温度进行训练训练软目标和一个小权重的硬目标。测试时,将温度T调整回1
通过知识蒸馏,可以将Teacher模型中的知识转移到Student模型,这样得到的Student模型要比直接训练的训练的相同模型有更好的泛化效果
如果复杂模型(Teacher)是一个集成模型,它组合了多个基模型,那么通过蒸馏Teacher训练得到的单个基模型,相比于直接训练的单个基模型有更好的泛化效果
Teacher模型如果能更加准确(一般大模型能够带来更高的准确率),那么它“教”出来的Student不一定更准确。这是因为Teacher和Student之间存在容量的差距
可以使用提早停止训练的方法,来减缓Teacher和Student模型之间的容量差距带来的结果,但并不能解决
Teacher和Student模型之间的容量差距问题,可以在中间引入一个助教来减缓后果,最佳的助教其效果最好处于Teacher和Student模型效果的均值水平上
————————————————
版权声明:本文为CSDN博主「阿文脑袋瓦特了」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/github_37848566/article/details/109709161
更多推荐
所有评论(0)