前置知识
这三个函数在深度学习模型中十分常见,尤其是在知识蒸馏领域,经常会将这三个函数进行比较
1、Softmax函数
softmax函数通常作为多分类以及归一化函数使用,其公式如下:
s
o
f
t
m
a
x
(
x
)
=
e
x
i
∑
i
=
1
e
x
i
softmax(x)=\frac{e^{x_i}}{\sum_{i=1} e^{x_i}}
softmax(x)=∑i=1exiexi
softmax函数有些重点的特点:
- 所有经过softmax输出数值总和为1且大于0,这满足一个概率分布。这点很好理解,因为分母是个求和,所有分式分子加起来就会得到分母
- 扩大化大小差距。这是由指数函数 e x e^x ex造成的,根据指数函数图像,自变量值 x x x越大,其因变量 y y y值增长的越快。可以看下面这个例子
x | 1 | 2 | 3 | 4 |
---|---|---|---|---|
softmax(x) | 0.032 | 0.087 | 0.237 | 0.644 |
这就进一步带来一个问题,是否可以通过一个方法,使数之间差距没有那么大呢?这里我们使用了一个超参数温度T,来控制差距,公式如下:
s
o
f
t
m
a
x
(
x
,
T
)
=
e
x
i
t
∑
i
=
1
e
x
i
t
softmax(x,T)=\frac{e^\frac {x_i}t}{\sum_{i=1} e^\frac {x_i}t}
softmax(x,T)=∑i=1etxietxi
然后接着之前的例子,我们令T=0.5,1,2,4时,观察数据的变化。
T\x | 1 | 2 | 3 | 4 |
---|---|---|---|---|
0.5 | 0.002 | 0.016 | 0.117 | 0.865 |
1 | 0.032 | 0.087 | 0.237 | 0.644 |
2 | 0.101 | 0.167 | 0.276 | 0.455 |
4 | 0.165 | 0.212 | 0.272 | 0.350 |
可以发现随着
T
T
T的增大,不同类别之间的差距值越小(对负标签,即非正确标签关注度更高),但是大小关系并不改变。下图是另一个softmax值与温度的关系图。
2、log_softmax函数
log_softmax函数就是将softmax得到的输出值作为对数函数的输入值
l
o
g
(
s
o
f
t
m
a
x
(
x
)
)
log(softmax(x))
log(softmax(x))
NLLLoss函数
NLLloss是衡量两者之间的差距,公式如下:
N
L
L
l
o
s
s
(
p
,
q
)
=
−
∑
i
=
1
q
i
l
o
g
p
i
NLLloss(p,q)=-\sum_{i=1} q_ilogp_i
NLLloss(p,q)=−i=1∑qilogpi
这里涉及到信息熵的概念,小伙伴们可以通过我关于机器学习贝叶斯那一篇博客去了解。简单理解来说就是,
p
,
q
p,q
p,q两者差距越大则最后损失函数值越大,负号的作用就是为了满足这个关系
CrossEntropyLoss函数
CrossEntropy函数又称交叉熵损失函数,其实公式表现形式和NLL损失函数一致,但是
p
、
q
p、q
p、q具体含义不同,这里的
p
、
q
p、q
p、q是要经过log_softmax的【在pytorch中】
C
r
o
s
s
E
n
t
r
o
p
y
L
o
s
s
(
p
,
q
)
=
−
∑
i
=
1
q
i
l
o
g
p
i
CrossEntropyLoss(p,q)=-\sum_{i=1} q_ilogp_i
CrossEntropyLoss(p,q)=−i=1∑qilogpi
KLDivLoss函数
KLDivLoss是用来判断两个分布的拟合/相似/匹配程度,假设现在有两个概率分布
P
、
Q
P、Q
P、Q,它们的KL散度分别为:
D
K
L
(
P
∣
∣
Q
)
=
−
∑
i
P
(
i
)
l
n
Q
(
i
)
P
(
i
)
=
∑
i
P
(
i
)
l
n
P
(
i
)
Q
(
i
)
D
K
L
(
p
∣
∣
q
)
=
∑
i
p
(
x
i
)
l
n
p
(
x
i
)
q
(
x
i
)
=
∑
i
p
(
x
i
)
[
l
o
g
(
p
(
x
i
)
)
−
l
o
g
(
q
(
x
i
)
)
]
D_{KL}(P||Q)=-\sum_i P(i)ln\frac{Q(i)}{P(i)}=\sum_i P(i)ln\frac{P(i)}{Q(i)}\\ D_{KL}(p||q)=\sum_i p(x_i)ln\frac{p(x_i)}{q(x_i)}=\sum_i p(x_i)[log(p(x_i))-log({q(x_i)})]
DKL(P∣∣Q)=−i∑P(i)lnP(i)Q(i)=i∑P(i)lnQ(i)P(i)DKL(p∣∣q)=i∑p(xi)lnq(xi)p(xi)=i∑p(xi)[log(p(xi))−log(q(xi))]
KLDivLoss适合用于连续分布的距离度量;并且对离散采用的连续输出空间分布进行回归通常很有用
NLLLoss与CrossEntropyLoss、KLDivLoss区别
NLLLoss与CrossEntropyLoss的区别在于一个log_softmax()函数,KLDivLoss与其它两者的区别在于其实两个KL散度之差再求和,而另外两者是求和(当然具体公式会有一定区别)
#NLLloss
def forward()
x=self.fc2(x)
x=F.log_softmax(x,dim=1)
return x
F.nll_loss()
#CrossEntropy
def forward()
x=self.fc2(x)
return x
F.cross_entropy()