知识蒸馏 - 视觉模型知识蒸馏Vision-KD-Trainer KL散度公式变化
flyfish
代码抄自
https://github.com/shaoshengsong/KDTrainer
代码分析的是Vision-KD-Trainer/helloworld.py
Python 版本: 3.12.9
PyTorch: 2.6.0+cu124
Transformers: 4.55.0
PEFT: 0.15.2
PyYAML: 6.0.2
环境搭建好之后 执行 python helloworld.py 纯绿色版
最好先看完基础知识
知识蒸馏 - 通过引入温度参数T调整 Softmax 的输出
知识蒸馏 - 自信息量是单个事件的信息量,而平均自信息量(即信息熵)是所有事件自信息量以其概率为权重的加权平均值
对于两个概率分布
P
P
P(真实分布)和
Q
Q
Q(模型预测分布),KL散度的定义是:
D
K
L
(
P
∥
Q
)
=
∑
x
P
(
x
)
log
(
P
(
x
)
Q
(
x
)
)
D_{KL}(P \| Q) = \sum_{x} P(x) \log\left( \frac{P(x)}{Q(x)} \right)
DKL(P∥Q)=x∑P(x)log(Q(x)P(x))
怎么就变成如下公式呢
D K L ( P ∥ Q ) = ∑ x P ( x ) log P ( x ) − ∑ x P ( x ) log Q ( x ) D_{KL}(P \| Q) = \sum_{x} P(x) \log P(x) - \sum_{x} P(x) \log Q(x) DKL(P∥Q)=x∑P(x)logP(x)−x∑P(x)logQ(x)
商的对数等于对数的差
“商的对数等于对数的差”就是:两个数相除的对数,等于这两个数分别取对数后再相减。
log c ( a b ) = log c a − log c b \log_c \left( \frac{a}{b} \right) = \log_c a - \log_c b logc(ba)=logca−logcb
先搞懂“对数”到底是啥
对数其实是“指数的反过来”。比如“以c为底a的对数”(写成
log
c
a
\log_c a
logca),本质是在问:“c的多少次方等于a?”
假设这个“多少次方”是x,那就能写成:
x
=
log
c
a
x = \log_c a
x=logca
反过来,也可以说:
c
x
=
a
c^x = a
cx=a(c的x次方等于a)。
给两个数的对数起个名字
现在有两个正数a和b(因为对数里的数必须是正数)。
按上面的逻辑:
- 设“c的多少次方等于a”是x,也就是 x = log c a x = \log_c a x=logca,所以 a = c x a = c^x a=cx;
- 设“c的多少次方等于b”是y,也就是 y = log c b y = \log_c b y=logcb,所以 b = c y b = c^y b=cy。
看看a除以b等于啥
我们想算
a
÷
b
a \div b
a÷b(也就是
a
b
\frac{a}{b}
ba),代入上面的
a
=
c
x
a = c^x
a=cx和
b
=
c
y
b = c^y
b=cy,得到:
a
b
=
c
x
c
y
\frac{a}{b} = \frac{c^x}{c^y}
ba=cycx
这里用到一个指数的常识:同底数的幂相除,底数不变,指数相减。比如
2
5
÷
2
3
=
2
5
−
3
=
2
2
2^5 \div 2^3 = 2^{5-3} = 2^2
25÷23=25−3=22。
所以
c
x
c
y
=
c
x
−
y
\frac{c^x}{c^y} = c^{x - y}
cycx=cx−y,也就是:
a
b
=
c
x
−
y
\frac{a}{b} = c^{x - y}
ba=cx−y
把上面的结果转成对数
现在看
a
b
=
c
x
−
y
\frac{a}{b} = c^{x - y}
ba=cx−y,这句话用对数的话来说就是:“c的(x - y)次方等于
a
b
\frac{a}{b}
ba”。
按对数的定义,“c的多少次方等于
a
b
\frac{a}{b}
ba”,这个“多少次方”就是
log
c
(
a
b
)
\log_c \left( \frac{a}{b} \right)
logc(ba)。
所以:
log
c
(
a
b
)
=
x
−
y
\log_c \left( \frac{a}{b} \right) = x - y
logc(ba)=x−y
换回原来的对数
前面已经知道
x
=
log
c
a
x = \log_c a
x=logca,
y
=
log
c
b
y = \log_c b
y=logcb,代入上面的式子,得到:
log
c
(
a
b
)
=
log
c
a
−
log
c
b
\log_c \left( \frac{a}{b} \right) = \log_c a - \log_c b
logc(ba)=logca−logcb
这样两个数相除的对数,等于这两个数的对数相减。
求和可以和加法、乘法(常数倍)交换顺序
求和的线性性质是求和可以和加法、乘法(常数倍)“交换顺序”。
规则
设 f ( x ) f(x) f(x) 和 g ( x ) g(x) g(x) 是任意两个关于 x x x 的函数, c c c 是任意常数(与 x x x 无关),则:
-
对加法的分配性:
两个函数相加后的求和,等于两个函数分别求和后再相加。
公式:
∑ x [ f ( x ) + g ( x ) ] = ∑ x f ( x ) + ∑ x g ( x ) \sum_{x} \left[ f(x) + g(x) \right] = \sum_{x} f(x) + \sum_{x} g(x) x∑[f(x)+g(x)]=x∑f(x)+x∑g(x) -
对常数倍的分配性:
常数乘以函数后的求和,等于常数乘以该函数的求和。
公式:
∑ x [ c ⋅ f ( x ) ] = c ⋅ ∑ x f ( x ) \sum_{x} \left[ c \cdot f(x) \right] = c \cdot \sum_{x} f(x) x∑[c⋅f(x)]=c⋅x∑f(x)
“乘法分配律”(如 c ⋅ ( a + b ) = c ⋅ a + c ⋅ b c \cdot (a + b) = c \cdot a + c \cdot b c⋅(a+b)=c⋅a+c⋅b),求和的线性性质本质是“求和符号对加法和常数倍的分配”。
比如:
-
若 x x x 只能取1和2, f ( 1 ) = 2 f(1)=2 f(1)=2, f ( 2 ) = 3 f(2)=3 f(2)=3; g ( 1 ) = 1 g(1)=1 g(1)=1, g ( 2 ) = 4 g(2)=4 g(2)=4,则:
左边 ∑ [ f ( x ) + g ( x ) ] = ( 2 + 1 ) + ( 3 + 4 ) = 3 + 7 = 10 \sum [f(x)+g(x)] = (2+1)+(3+4) = 3+7=10 ∑[f(x)+g(x)]=(2+1)+(3+4)=3+7=10,
右边 ∑ f ( x ) + ∑ g ( x ) = ( 2 + 3 ) + ( 1 + 4 ) = 5 + 5 = 10 \sum f(x) + \sum g(x) = (2+3)+(1+4)=5+5=10 ∑f(x)+∑g(x)=(2+3)+(1+4)=5+5=10,两边相等,验证了第一条规则。 -
若 c = 2 c=2 c=2,则:
左边 ∑ [ 2 ⋅ f ( x ) ] = 2 ⋅ 2 + 2 ⋅ 3 = 4 + 6 = 10 \sum [2 \cdot f(x)] = 2 \cdot 2 + 2 \cdot 3 = 4 + 6 = 10 ∑[2⋅f(x)]=2⋅2+2⋅3=4+6=10,
右边 2 ⋅ ∑ f ( x ) = 2 ⋅ ( 2 + 3 ) = 2 ⋅ 5 = 10 2 \cdot \sum f(x) = 2 \cdot (2+3) = 2 \cdot 5 = 10 2⋅∑f(x)=2⋅(2+3)=2⋅5=10,两边相等,验证了第二条规则。
具体到KL散度
对数性质,将KL散度写成:
D
K
L
(
P
∥
Q
)
=
∑
x
P
(
x
)
⋅
[
log
P
(
x
)
−
log
Q
(
x
)
]
D_{KL}(P \| Q) = \sum_{x} P(x) \cdot \left[ \log P(x) - \log Q(x) \right]
DKL(P∥Q)=x∑P(x)⋅[logP(x)−logQ(x)]
现在要拆分成两个求和项,步骤如下:
步骤1:先展开括号里的乘法
根据乘法分配律(即
a
⋅
(
b
−
c
)
=
a
⋅
b
−
a
⋅
c
a \cdot (b - c) = a \cdot b - a \cdot c
a⋅(b−c)=a⋅b−a⋅c),括号里的减法可以和外面的
P
(
x
)
P(x)
P(x)分别相乘:
P
(
x
)
⋅
[
log
P
(
x
)
−
log
Q
(
x
)
]
=
P
(
x
)
⋅
log
P
(
x
)
−
P
(
x
)
⋅
log
Q
(
x
)
P(x) \cdot \left[ \log P(x) - \log Q(x) \right] = P(x) \cdot \log P(x) - P(x) \cdot \log Q(x)
P(x)⋅[logP(x)−logQ(x)]=P(x)⋅logP(x)−P(x)⋅logQ(x)
步骤2:应用求和的线性性质
将上式代入KL散度的表达式,得到:
D
K
L
(
P
∥
Q
)
=
∑
x
[
P
(
x
)
log
P
(
x
)
−
P
(
x
)
log
Q
(
x
)
]
D_{KL}(P \| Q) = \sum_{x} \left[ P(x) \log P(x) - P(x) \log Q(x) \right]
DKL(P∥Q)=x∑[P(x)logP(x)−P(x)logQ(x)]
此时,求和符号后面是两个项的差(即
f
(
x
)
−
g
(
x
)
f(x) - g(x)
f(x)−g(x),
其中
f
(
x
)
=
P
(
x
)
log
P
(
x
)
f(x) = P(x)\log P(x)
f(x)=P(x)logP(x),
g
(
x
)
=
P
(
x
)
log
Q
(
x
)
g(x) = P(x)\log Q(x)
g(x)=P(x)logQ(x))。
根据求和的线性性质 ∑ ( f − g ) = ∑ f − ∑ g \sum (f - g) = \sum f - \sum g ∑(f−g)=∑f−∑g,可以直接拆分:
∑ x [ P ( x ) log P ( x ) − P ( x ) log Q ( x ) ] = ∑ x P ( x ) log P ( x ) − ∑ x P ( x ) log Q ( x ) \sum_{x} \left[ P(x) \log P(x) - P(x) \log Q(x) \right] = \sum_{x} P(x) \log P(x) - \sum_{x} P(x) \log Q(x) x∑[P(x)logP(x)−P(x)logQ(x)]=x∑P(x)logP(x)−x∑P(x)logQ(x)