“天作之合”softmax与CrossEntropy
本文从 max \text{max} max到 logsumexp \operatorname{logsumexp} logsumexp,再到 softmax \text{softmax} softmax进行了一个简单推导,最后说明了 softmax \text{softmax} softmax与CrossEntropy的关系。希望帮助大家理解多分类损失函数CrossEntropy。
max
首先,给出
max
\text{max}
max 函数的表达式
max
(
x
1
,
x
2
,
…
,
x
n
)
=
lim
K
→
+
∞
1
K
log
(
∑
i
=
1
n
e
K
x
i
)
\max \left(x_{1}, x_{2}, \ldots, x_{n}\right)=\lim _{K \rightarrow+\infty} \frac{1}{K} \log \left(\sum_{i=1}^{n} e^{K x_{i}}\right)
max(x1,x2,…,xn)=K→+∞limK1log(i=1∑neKxi)
这个式子怎么来的,详见:链接
然后,选定常数
K
K
K,就有近似
max
(
x
1
,
x
2
,
…
,
x
n
)
≈
1
K
log
(
∑
i
=
1
n
e
K
x
i
)
\max \left(x_{1}, x_{2}, \ldots, x_{n}\right) \approx \frac{1}{K} \log \left(\sum_{i=1}^{n} e^{K x_{i}}\right)
max(x1,x2,…,xn)≈K1log(i=1∑neKxi)
在模型中,很多时候可以设
K
=
1
K=1
K=1 ,这等价于把
K
K
K 融合到模型自身之中,所以最简单地有
max
\text{max}
max的光滑近似:
max
(
x
1
,
x
2
,
…
,
x
n
)
≈
log
(
∑
i
=
1
n
e
x
i
)
≜
logsumexp
(
x
1
,
x
2
,
…
,
x
n
)
\begin{aligned} \max \left(x_{1}, x_{2}, \ldots, x_{n}\right) & \approx \log \left(\sum_{i=1}^{n} e^{x_{i}}\right) \\ & \triangleq \operatorname{logsumexp}\left(x_{1}, x_{2}, \ldots, x_{n}\right) \end{aligned}
max(x1,x2,…,xn)≈log(i=1∑nexi)≜logsumexp(x1,x2,…,xn)
很多时候 x x x 也是学习而来的,直接设 K = 1 K=1 K=1 ,相当于让模型自己决定 K K K 的大小
softmax
softmax \text{softmax} softmax不是 max \text{max} max的光滑近似,而是 onehot ( arg max ( x ) ) \operatorname{onehot}(\arg \max (\boldsymbol{x})) onehot(argmax(x))的光滑近似
onehot
(
arg
max
(
x
)
)
\operatorname{onehot}(\arg \max (\boldsymbol{x}))
onehot(argmax(x)):先求出最大值所在的位置,然后生成一个等长的向量,最大值那一位置1,其它位置都置0。例如:
[
2
,
1
,
4
,
5
,
3
]
→
[
0
,
0
,
0
,
1
,
0
]
[2,1,4,5,3] \quad \rightarrow \quad[0,0,0,1,0]
[2,1,4,5,3]→[0,0,0,1,0]
简单推导 logsumexp=>softmax \text { logsumexp=>softmax } logsumexp=>softmax
给出向量
x
=
[
x
1
,
x
2
,
…
,
x
n
]
\boldsymbol{x}=\left[x_{1}, x_{2}, \ldots, x_{n}\right]
x=[x1,x2,…,xn],然后每一位都减去整体的最大值,得到
x
′
=
[
x
1
,
x
2
,
…
,
x
n
]
−
max
(
x
1
,
x
2
,
…
,
x
n
)
\boldsymbol{x}^{\prime}=\left[x_{1}, x_{2}, \ldots, x_{n}\right]-\max \left(x_{1}, x_{2}, \ldots, x_{n}\right)
x′=[x1,x2,…,xn]−max(x1,x2,…,xn),这样新向量
x
′
\boldsymbol{x}^{\prime}
x′与原向量
x
\boldsymbol{x}
x最大值所在位置是一样的,即
onehot
(
arg
max
(
x
)
)
=
onehot
(
arg
max
(
x
′
)
)
\text{onehot}(\arg \max (\boldsymbol{x}))=\operatorname{onehot}\left(\arg \max \left(\boldsymbol{x}^{\prime}\right)\right)
onehot(argmax(x))=onehot(argmax(x′))
。
不失一般性,假设 x 1 , x 2 , … , x n x_{1}, x_{2}, \ldots, x_{n} x1,x2,…,xn两两不相等,那么新向量 x ′ \boldsymbol{x}^{\prime} x′的最大值显然为0,并且除去最大值外,其余各位都是负数。
那么,考虑对新向量
x
′
\boldsymbol{x}^{\prime}
x′取指数得到
e
x
′
=
[
e
x
1
−
max
(
x
1
,
x
2
,
…
,
x
n
)
,
e
x
2
−
max
(
x
1
,
x
2
,
…
,
x
n
)
,
…
,
e
x
n
−
max
(
x
1
,
x
2
,
…
,
x
n
)
]
e^{\boldsymbol{x}^{\prime}}=\left[e^{x_{1}-\max \left(x_{1}, x_{2}, \ldots, x_{n}\right)}, e^{x_{2}-\max \left(x_{1}, x_{2}, \ldots, x_{n}\right)}, \ldots, e^{x_{n}-\max \left(x_{1}, x_{2}, \ldots, x_{n}\right)}\right]
ex′=[ex1−max(x1,x2,…,xn),ex2−max(x1,x2,…,xn),…,exn−max(x1,x2,…,xn)]
作为 onehot ( arg max ( x ′ ) ) \text{onehot}\left(\arg \max \left(\boldsymbol{x}^{\prime}\right)\right) onehot(argmax(x′)) 的近似,因为最大值为0,所以对应的位置是 e 0 = 1 e^{0}=1 e0=1 ,而其余为负,取指数后会比较接近于 0。
此时,将
max
(
x
1
,
x
2
,
…
,
x
n
)
≈
log
(
∑
i
=
1
n
e
x
i
)
\max \left(x_{1}, x_{2}, \ldots, x_{n}\right) \approx \log \left(\sum_{i=1}^{n} e^{x_{i}}\right)
max(x1,x2,…,xn)≈log(∑i=1nexi)带入上式得到
onehot
(
arg
max
(
x
)
)
=
onehot
(
arg
max
(
x
′
)
)
≈
(
e
x
1
∑
i
=
1
n
e
x
i
,
e
x
2
∑
i
=
1
n
e
x
i
,
…
,
e
x
n
∑
i
=
1
n
e
x
i
)
≜
softmax
(
x
1
,
x
2
,
…
,
x
n
)
\begin{aligned} \operatorname{onehot}(\arg \max (\boldsymbol{x})) &=\operatorname{onehot}\left(\arg \max \left(\boldsymbol{x}^{\prime}\right)\right) \\ & \approx\left(\frac{e^{x_{1}}}{\sum_{i=1}^{n} e^{x_{i}}}, \frac{e^{x_{2}}}{\sum_{i=1}^{n} e^{x_{i}}}, \ldots, \frac{e^{x_{n}}}{\sum_{i=1}^{n} e^{x_{i}}}\right) \\ & \triangleq \operatorname{softmax}\left(x_{1}, x_{2}, \ldots, x_{n}\right) \end{aligned}
onehot(argmax(x))=onehot(argmax(x′))≈(∑i=1nexiex1,∑i=1nexiex2,…,∑i=1nexiexn)≜softmax(x1,x2,…,xn)
softmax的作用
softmax
\text{softmax}
softmax的作用是把一个序列,变成概率。
P
(
x
)
:
[
x
1
x
2
⋯
x
n
]
→
[
P
1
P
2
⋯
P
n
]
P(\mathbf{x}):\left[\begin{array}{c} x_{1} \\ x_{2} \\ \cdots \\ x_{n} \end{array}\right] \rightarrow\left[\begin{array}{c} P_{1} \\ P_{2} \\ \cdots \\ P_{n} \end{array}\right]
P(x):
x1x2⋯xn
→
P1P2⋯Pn
P
j
=
e
x
j
∑
i
=
1
n
e
x
i
∀
j
∈
1
⋯
N
P_{j}=\frac{e^{x_{j}}}{\sum_{i=1}^{n} e^{x_{i}}} \quad \forall j \in 1 \cdots N
Pj=∑i=1nexiexj∀j∈1⋯N
从概率的角度解释
softmax
\text{softmax}
softmax 的话,就是
P
j
=
P
(
y
=
j
∣
x
)
P_{j}=\boldsymbol{P}(y=j \mid x)
Pj=P(y=j∣x)
softmax的实现以及数值稳定性
代码实现:
def softmax(x):
"""Compute the softmax of vector x."""
exps = np.exp(x)
return exps / np.sum(exps)
但是这种方法非常的不稳定。因为这种方法要算指数,只要你的输入稍微大一点,比如:
[
10000
,
20000
,
30000
]
[10000,20000,30000]
[10000,20000,30000]
分母上就是
e
10000
+
e
20000
+
e
30000
e^{10000}+e^{20000}+e^{30000}
e10000+e20000+e30000
很明显,在计算上一定会溢出。
解决办法:在分子分母上都乘上一个系数,减小数值大小,同时保证整体还是对的
P
j
=
e
x
j
∑
i
=
1
n
e
x
i
=
C
e
x
j
∑
i
=
1
n
C
e
x
i
P_{j}=\frac{e^{x_{j}}}{\sum_{i=1}^{n} e^{x_{i}}}=\frac{C e^{x_{j}}}{\sum_{i=1}^{n} C e^{x_{i}}}
Pj=∑i=1nexiexj=∑i=1nCexiCexj
常数
C
C
C吸收进指数里面
P
j
=
e
x
j
+
log
(
C
)
∑
i
=
1
n
e
x
i
+
log
(
C
)
P
j
=
e
x
j
+
D
∑
i
=
1
n
e
x
i
+
D
\begin{aligned} P_{j} &=\frac{e^{x_{j}+\log (C)}}{\sum_{i=1}^{n} e^{x_{i }+\log (C)}} \\ P_{j} &=\frac{e^{x_{j}+D}}{\sum_{i=1}^{n} e^{x_{i}+D}} \end{aligned}
PjPj=∑i=1nexi+log(C)exj+log(C)=∑i=1nexi+Dexj+D
这里的
D
D
D一般取
D
=
−
max
(
x
1
,
x
2
,
⋯
,
x
n
)
D=-\max \left(x_{1}, x_{2}, \cdots, x_{n}\right)
D=−max(x1,x2,⋯,xn)
代码实现:
def stablesoftmax(x):
"""Compute the softmax of vector x in a numerically stable way."""
shiftx = x - np.max(x)
exps = np.exp(shiftx)
return exps / np.sum(exps)
输入差别过大时,还是会有数值稳定性问题。
Softmax_Cross_Entropy的实现方式如下
log
(
P
j
)
=
log
(
e
x
j
∑
i
=
1
i
e
x
i
)
=
log
(
e
x
j
)
−
log
(
∑
i
=
1
n
e
x
i
)
=
x
j
−
log
(
∑
i
=
1
n
e
x
i
)
\begin{gathered} \log \left(P_{j}\right)=\log \left(\frac{e^{x_{j}}}{\sum_{i=1}^{i} e^{x_{i}}}\right) \\ =\log \left(e^{x_{j}}\right)-\log \left(\sum_{i=1}^{n} e^{x_{i}}\right) \\ =x_{j}-\log \left(\sum_{i=1}^{n} e^{x_{i}}\right) \end{gathered}
log(Pj)=log(∑i=1iexiexj)=log(exj)−log(i=1∑nexi)=xj−log(i=1∑nexi)
LogSoftmax省了一个指数计算,省了一个除法,数值上相对稳定一些。
softmax与CrossEntropy
softmax \text{softmax} softmax本身没有太大关系,只是把这两个放在一起计算,算起来更快,数值稳定性也更好一些。
CrossEntropy
交叉熵本质是衡量两个概率分布的距离的,而softmax能把一切转换成概率分布,那么这两者就是“天作之合”。
交叉熵举例说明:
假设一个动物照片的数据集中有5种动物,且每张照片中只有一只动物,每张照片的标签都是one-hot编码。
Animal
Dog
Fox
Horse
Eagle
Squirrel
Label
[
1
,
0
,
0
,
0
,
0
]
[
0
,
1
,
0
,
0
,
0
]
[
0
,
0
,
1
,
0
,
0
]
[
0
,
0
,
0
,
1
,
0
]
[
0
,
0
,
0
,
0
,
1
]
\begin{array}{|l|l|l|l|l|l|} \hline \text { Animal } & \text { Dog } & \text { Fox } & \text { Horse } & \text { Eagle } & \text { Squirrel } \\ \hline \text { Label } & {[1,0,0,0,0]} & {[0,1,0,0,0]} & {[0,0,1,0,0]} & {[0,0,0,1,0]} & {[0,0,0,0,1]} \\ \hline \end{array}
Animal Label Dog [1,0,0,0,0] Fox [0,1,0,0,0] Horse [0,0,1,0,0] Eagle [0,0,0,1,0] Squirrel [0,0,0,0,1]
第一张照片是狗的概率为100%,是其他的动物的概率是0;第二张照片是狐狸的概率是100%,是其他动物的概率是0,其余照片同理;因此可以计算下,每张照片的熵都为0。换句话说,以one-hot编码作为标签的每张照片都有100%的确定度,不像别的描述概率的方式:狗的概率为90%,猫的概率为10%。
假设有两个机器学习模型对第一张照片分别作出了预测:Q1和Q2,而第一张照片的真实标签为[1,0,0,0,0]。
Model Prediction Q1 [ 0.4 , 0.3 , 0.05 , 0.05 , 0.2 ] Q2 [ 0.98 , 0.01 , 0 , 0 , 0.01 ] \begin{array}{|l|l|} \hline \text { Model } & \text { Prediction } \\ \hline \text { Q1 } & {[0.4,0.3,0.05,0.05,0.2]} \\ \hline \text { Q2 } & {[0.98,0.01,0,0,0.01]} \\ \hline \end{array} Model Q1 Q2 Prediction [0.4,0.3,0.05,0.05,0.2][0.98,0.01,0,0,0.01]
两个模型预测效果如何呢,可以分别计算下交叉熵:
H
(
P
1
,
Q
1
)
=
−
∑
i
P
1
(
i
)
log
2
Q
1
(
i
)
=
−
(
1
log
0.4
+
0
log
0.3
+
0
log
0.05
+
0
log
0.05
+
0
log
0.2
)
≈
0.916
H
(
P
1
,
Q
2
)
=
−
∑
i
P
1
(
i
)
log
2
Q
2
(
i
)
=
−
(
1
log
0.98
+
0
log
0.01
+
0
log
0
+
0
log
0
+
0
log
0.01
)
≈
0.02
\begin{gathered} H\left(P_{1}, Q_{1}\right)=-\sum_{i} P_{1}(i) \log _{2} Q_{1}(i) \\ =-(1 \log 0.4+0 \log 0.3+0 \log 0.05+0 \log 0.05+0 \log 0.2) \approx 0.916 \\ H\left(P_{1}, Q_{2}\right)=-\sum_{i} P_{1}(i) \log _{2} Q_{2}(i) \\ =-(1 \log 0.98+0 \log 0.01+0 \log 0+0 \log 0+0 \log 0.01) \approx 0.02 \end{gathered}
H(P1,Q1)=−i∑P1(i)log2Q1(i)=−(1log0.4+0log0.3+0log0.05+0log0.05+0log0.2)≈0.916H(P1,Q2)=−i∑P1(i)log2Q2(i)=−(1log0.98+0log0.01+0log0+0log0+0log0.01)≈0.02
交叉熵公式:
H
(
L
,
P
)
=
−
∑
j
n
L
j
log
2
P
j
\begin{gathered} H\left(L, P\right)=-\sum_{j}^{n} L_j \log _{2} P_j \end{gathered}
H(L,P)=−j∑nLjlog2Pj
其中 P P P就是预测概率分布,而 L L L是真实标签分布。
参考博客
- https://zhuanlan.zhihu.com/p/149186719
- https://spaces.ac.cn/archives/6620
- https://www.zhihu.com/question/294679135/answer/885285177