文章目录
- 一、信息量、熵、交叉熵、相对熵/KL散度、交叉熵损失
-
- [1、信息量 Amount of Information](#1、信息量 Amount of Information)
- [2、熵 Entropy](#2、熵 Entropy)
- [3、交叉熵 Cross Entropy](#3、交叉熵 Cross Entropy)
- [4、相对熵 Relative Entropy 、KL散度 KL Divergence](#4、相对熵 Relative Entropy 、KL散度 KL Divergence)
- [4、交叉熵损失 Cross Entropy Loss](#4、交叉熵损失 Cross Entropy Loss)
- 二、交叉熵损失函数
- [三、二元交叉熵损失函数 Binary Cross Entropy Loss](#三、二元交叉熵损失函数 Binary Cross Entropy Loss)
-
- 1、二元交叉熵损失函数
- [2、nn.BCELoss() 类](#2、nn.BCELoss() 类)
- 3、使用场景举例
- [4、`torch.nn.BCEWithLogitsLoss()` 与 `nn.BCELoss()` 的区别](#4、
torch.nn.BCEWithLogitsLoss()
与nn.BCELoss()
的区别) - [5、`torch.nn.BCEWithLogitsLoss()` 类](#5、
torch.nn.BCEWithLogitsLoss()
类)
名称 | 公式 |
---|---|
信息量 | I ( x ) = log 2 ( 1 p ( x ) ) = − log 2 ( p ( x ) ) I(x) = \log_2\left(\frac{1}{p(x)}\right) = -\log_2(p(x)) I(x)=log2(p(x)1)=−log2(p(x)) |
熵 | H ( p ) = ∑ p i I i p = − ∑ p i log 2 ( p i ) H(p) = \sum p_i I_i^p = -\sum p_i \log_2(p_i) H(p)=∑piIip=−∑pilog2(pi) |
交叉熵 | H ( p , q ) = ∑ p i I i q = − ∑ p i log 2 ( q i ) H(p, q) = \sum p_i I_i^q = -\sum p_i \log_2(q_i) H(p,q)=∑piIiq=−∑pilog2(qi) |
相对熵(KL散度) | D K L ( p ∣ ∣ q ) = ∑ p i log 2 ( p i q i ) D_{KL}(p \vert \vert q) = \sum p_i \log_2\left(\frac{p_i}{q_i}\right) DKL(p∣∣q)=∑pilog2(qipi) |
交叉熵损失函数 | C r o s s _ E n t r o p y _ L o s s = H ( p , q ) = − log 2 ( q c l a s s ) Cross\_Entropy\Loss = H(p, q) = -\log_2(q{class}) Cross_Entropy_Loss=H(p,q)=−log2(qclass) |
参考Axure
一、信息量、熵、交叉熵、相对熵/KL散度、交叉熵损失
1、信息量 Amount of Information
- 定义:事件包含的信息量大小(事件发生的难度有多大)
- 小概率事件,它发生的难度比较大,所以有较大的信息量
- 大概率事件,它发生的难度比较小,所以有较小的信息量
这里举个例子
事件 | 具体情况 | P P P | 事件类型 | 发生难度 | 信息量 |
---|---|---|---|---|---|
事件A | 小明考试及格 | P ( A ) = 20 % P(A)=20\% P(A)=20% | 小概率事件 | 大 | 大 |
事件B | 小明考试不及格 | P ( B ) = 80 % P(B)=80\% P(B)=80% | 大概率事件 | 小 | 小 |
如果小明考及格了,事件A发生的难度大,可能发愤图强了,可能作弊打小抄了,可能老师打错分了,肯能蒙得全对了...所以事件B发生的背后可能有很多事发生,所以信息量很大;如果B发生了,小明考及格了只是正常发挥,没啥大不了。
- 性质 :对于独立事件A、B: p ( A B ) = p ( A ) p ( B ) p(AB) = p(A)p(B) p(AB)=p(A)p(B),两个事件同时发生的信息量等于两个事件的信息量相加:
I ( A B ) = I ( A ) + I ( B ) I(AB) = I(A) + I(B) I(AB)=I(A)+I(B)
- 信息量公式 : I ( x ) : = l o g 2 ( 1 p ( x ) ) = − l o g 2 ( p ( x ) ) I(x) := log_2(\frac{1}{p(x)}) = -log_2(p(x)) I(x):=log2(p(x)1)=−log2(p(x))
:=
是'定义为'的意思,不是等号的意思,通常用于定义函数公式- p ( x ) p(x) p(x) 表示事件发生的概率,取值范围 0 ≤ p ( x ) ≤ 1 0 \leq p(x) \leq 1 0≤p(x)≤1

这个定义式是人为定义设计的,为什么这么定义呢?
- 根据定义 ,概率 p ( x ) p(x) p(x)和信息量 I ( x ) I(x) I(x)是负相关的,暂且定义为反比例函数, I ( x ) : = 1 p ( x ) I(x) := \frac{1}{p(x)} I(x):=p(x)1
- 根据性质 两个事件同时发生的信息量等于两个事件的信息量相加,即 I ( A B ) = I ( A ) + I ( B ) I(AB) = I(A) + I(B) I(AB)=I(A)+I(B),由此推导出 I ( x ) = l o g 2 ( 1 p ( x ) ) I(x) = log_2(\frac{1}{p(x)}) I(x)=log2(p(x)1)。所以用了对数的加法性质。
- 以2为底,是转换到二进制下的表示复杂度,(其实以e为底、以10为底都可以,只不过以2为底更优)
这里验证一下独立事件的性质:
I ( A B ) = log 2 ( 1 p ( A B ) ) = log 2 ( 1 p ( A ) p ( B ) ) = log 2 ( 1 p ( A ) ) + log 2 ( 1 p ( B ) ) = I ( A ) + I ( B ) I(AB) = \log_2\left(\frac{1}{p(AB)}\right) = \log_2\left(\frac{1}{p(A)p(B)}\right) = \log_2\left(\frac{1}{p(A)}\right) + \log_2\left(\frac{1}{p(B)}\right) = I(A) + I(B) I(AB)=log2(p(AB)1)=log2(p(A)p(B)1)=log2(p(A)1)+log2(p(B)1)=I(A)+I(B)
举个例子:抛规则和不规则的硬币
2、熵 Entropy
-
定义 :概率分布的信息量期望: H ( p ) : = E ( I ( x ) ) H(p) := E(I(x)) H(p):=E(I(x))
亦可理解为:系统整体的信息量。其中,系统整体由所有可能发生的事件构成。比如抛硬币,正面和反面就构成一个系统整体
-
公式:
H ( p ) = ∑ p i I i p = − ∑ p i l o g 2 ( p i ) H(p) = \sum p_i I_i^p = -\sum p_i log_2(p_i) H(p)=∑piIip=−∑pilog2(pi)
例子:假设一个系统含有两个事件,两个概率构成了概率分布
- 事件A: p ( A ) = 0.2 p_{(A)} = 0.2 p(A)=0.2, I ( A ) = l o g 2 ( 1 / p ( A ) ) = 2.32 I_{(A)} = log_2(1/p_{(A)}) = 2.32 I(A)=log2(1/p(A))=2.32
- 事件B: p ( B ) = 0.8 p_{(B)} = 0.8 p(B)=0.8, I ( B ) = l o g 2 ( 1 / p ( B ) ) = 0.32 I_{(B)} = log_2(1/p_{(B)}) = 0.32 I(B)=log2(1/p(B))=0.32
想用一个值来衡量这个系统所携带的信息量,用熵来表示,是概率分布的期望(所有事件的信息量的加权平均值,概率为权重)
H ( p ) = 0.2 ⋅ 2.32 + 0.8 ⋅ 0.32 = 0.72 H(p) = 0.2 \cdot 2.32 + 0.8 \cdot 0.32 = 0.72 H(p)=0.2⋅2.32+0.8⋅0.32=0.72
- 作用 :用来评估概率模型 的不确定性程度
- 不确定性越大,熵越大
- 不确定性越小,熵越小、
这里举个例子,平均分别和正态分布,平均分布的不确定性更高,因为每个事件发生的概率都相等,不确定哪个事情更会发生。
这里举个例子:
例1:抛硬币,正面概率 p ( A ) = 0.5 p_{(A)} = 0.5 p(A)=0.5,反面概率 p ( B ) = 0.5 p_{(B)} = 0.5 p(B)=0.5
H ( p ) = ∑ p i I i p = p ( A ) ⋅ log 2 ( 1 p ( A ) ) + p ( B ) ⋅ log 2 ( 1 p ( B ) ) = 0.5 ⋅ log 2 ( 1 0.5 ) + 0.5 ⋅ log 2 ( 1 0.5 ) = 0.5 ⋅ 1 + 0.5 ⋅ 1 = 1 \begin{align*} H(p) &= \sum p_i I_i^p \\ &= p_{(A)} \cdot \log_2\left(\frac{1}{p_{(A)}}\right) + p_{(B)} \cdot \log_2\left(\frac{1}{p_{(B)}}\right) \\ &= 0.5 \cdot \log_2\left(\frac{1}{0.5}\right) + 0.5 \cdot \log_2\left(\frac{1}{0.5}\right) \\ &= 0.5 \cdot 1 + 0.5 \cdot 1 \\ &= 1 \end{align*} H(p)=∑piIip=p(A)⋅log2(p(A)1)+p(B)⋅log2(p(B)1)=0.5⋅log2(0.51)+0.5⋅log2(0.51)=0.5⋅1+0.5⋅1=1
例2:抛硬币,正面概率 p ( A ) = 0.2 p_{(A)} = 0.2 p(A)=0.2,反面概率 p ( B ) = 0.8 p_{(B)} = 0.8 p(B)=0.8
H ( p ) = ∑ p i I i p = p ( A ) ⋅ log 2 ( 1 p ( A ) ) + p ( B ) ⋅ log 2 ( 1 p ( B ) ) = 0.2 ⋅ log 2 ( 1 0.2 ) + 0.8 ⋅ log 2 ( 1 0.8 ) = 0.2 ⋅ 2.32 + 0.8 ⋅ 0.32 = 0.72 \begin{align*} H(p) &= \sum p_i I_i^p \\ &= p_{(A)} \cdot \log_2\left(\frac{1}{p_{(A)}}\right) + p_{(B)} \cdot \log_2\left(\frac{1}{p_{(B)}}\right) \\ &= 0.2 \cdot \log_2\left(\frac{1}{0.2}\right) + 0.8 \cdot \log_2\left(\frac{1}{0.8}\right) \\ &= 0.2 \cdot 2.32 + 0.8 \cdot 0.32 \\ &= 0.72 \end{align*} H(p)=∑piIip=p(A)⋅log2(p(A)1)+p(B)⋅log2(p(B)1)=0.2⋅log2(0.21)+0.8⋅log2(0.81)=0.2⋅2.32+0.8⋅0.32=0.72
- 结论 :
- 若概率密度均匀,产生的随机变量的不确定性就更高,则熵的值就更大
- 若概率密度聚拢,产生的随机变量的不确定性就更低,则熵的值较小
3、交叉熵 Cross Entropy
- 假设 :真实概率分布为 p p p、预测概率分布(估计概率分布)为 q q q
- 定义 :预测概率分布 q q q 对真实的概率分布 p p p 的平均信息量的估计,叫做交叉熵
- 公式 : H ( p , q ) = ∑ p i I i q = − ∑ p i log 2 ( q i ) H(p,q) = \sum p_i I_i^q = -\sum p_i \log_2(q_i) H(p,q)=∑piIiq=−∑pilog2(qi)
- 和熵的计算公式相比,概率用的是真实分布的概率,信息量用的是预测概率分布的信息量
例1:抛硬币,正面真实概率 p ( A ) = 0.5 p(A) = 0.5 p(A)=0.5,反面真实概率 p ( B ) = 0.5 p(B) = 0.5 p(B)=0.5;正面估计概率 q ( A ) = 0.2 q(A) = 0.2 q(A)=0.2,反面估计概率 q ( B ) = 0.8 q(B) = 0.8 q(B)=0.8
H ( p , q ) = − ∑ p i log 2 ( q i ) = p ( A ) ⋅ log 2 ( 1 q ( A ) ) + p ( B ) ⋅ log 2 ( 1 q ( B ) ) = 0.5 ⋅ log 2 ( 1 0.2 ) + 0.5 ⋅ log 2 ( 1 0.8 ) = 0.5 ⋅ 2.32 + 0.5 ⋅ 0.32 = 1.32 \begin{align*} H(p,q) &= -\sum p_i \log_2(q_i) \\ &= p_{(A)} \cdot \log_2\left(\frac{1}{q_{(A)}}\right) + p_{(B)} \cdot \log_2\left(\frac{1}{q_{(B)}}\right) \\ &= 0.5 \cdot \log_2\left(\frac{1}{0.2}\right) + 0.5 \cdot \log_2\left(\frac{1}{0.8}\right) \\ &= 0.5 \cdot 2.32 + 0.5 \cdot 0.32 \\ &= 1.32 \end{align*} H(p,q)=−∑pilog2(qi)=p(A)⋅log2(q(A)1)+p(B)⋅log2(q(B)1)=0.5⋅log2(0.21)+0.5⋅log2(0.81)=0.5⋅2.32+0.5⋅0.32=1.32
例2:抛硬币,正面真实概率 p ( A ) = 0.5 p(A) = 0.5 p(A)=0.5,反面真实概率 p ( B ) = 0.5 p(B) = 0.5 p(B)=0.5;正面估计概率 q ( A ) = 0.4 q(A) = 0.4 q(A)=0.4,反面估计概率 q ( B ) = 0.6 q(B) = 0.6 q(B)=0.6H ( p , q ) = − ∑ p i log 2 ( q i ) = p ( A ) ⋅ log 2 ( 1 q ( A ) ) + p ( B ) ⋅ log 2 ( 1 q ( B ) ) = 0.5 ⋅ log 2 ( 1 0.4 ) + 0.5 ⋅ log 2 ( 1 0.6 ) = 0.5 ⋅ 1.32 + 0.5 ⋅ 0.74 = 1.03 \begin{align*} H(p,q) &= -\sum p_i \log_2(q_i) \\ &= p_{(A)} \cdot \log_2\left(\frac{1}{q_{(A)}}\right) + p_{(B)} \cdot \log_2\left(\frac{1}{q_{(B)}}\right) \\ &= 0.5 \cdot \log_2\left(\frac{1}{0.4}\right) + 0.5 \cdot \log_2\left(\frac{1}{0.6}\right) \\ &= 0.5 \cdot 1.32 + 0.5 \cdot 0.74 \\ &= 1.03 \end{align*} H(p,q)=−∑pilog2(qi)=p(A)⋅log2(q(A)1)+p(B)⋅log2(q(B)1)=0.5⋅log2(0.41)+0.5⋅log2(0.61)=0.5⋅1.32+0.5⋅0.74=1.03
- 结论
- 预估概率分布与真实概率分布越接近,交叉熵越小。
- 交叉熵的值总是大于真实概率分布的熵的值。证明是根据吉布斯不等式。
吉布斯不等式:
若 ∑ i = 1 n p i = ∑ i = 1 n q i = 1 \sum_{i=1}^{n} p_i = \sum_{i=1}^{n} q_i = 1 ∑i=1npi=∑i=1nqi=1,且 p i , q i ∈ ( 0 , 1 ] p_i, q_i \in (0,1] pi,qi∈(0,1],则有:
− ∑ i = 1 n p i log p i ≤ − ∑ i = 1 n p i log q i -\sum_{i=1}^{n} p_i \log p_i \leq -\sum_{i=1}^{n} p_i \log q_i −i=1∑npilogpi≤−i=1∑npilogqi
等号成立当且仅当 p i = q i ∀ i p_i = q_i \forall i pi=qi∀i
4、相对熵 Relative Entropy 、KL散度 KL Divergence
-
名称:KL散度以Kullback和Leibler的名字命名,也被称为相对熵
-
作用:用于衡量2个概率分布之间的差异,理解为两个分布信息量的差异
-
公式 :
D K L ( p ∣ ∣ q ) = ∑ p i [ I q − I p ] # I q − I p 为信息量之差 = ∑ p i [ log 2 ( 1 q i ) − log 2 ( 1 p i ) ] = ∑ p i log 2 ( 1 q i ) − ∑ p i log 2 ( 1 p i ) = H ( p , q ) − H ( p ) # 交叉熵减去前者基准分布 P 的熵 = ∑ p i log 2 ( p i q i ) \begin{align*} D_{KL}(p \vert \vert q) &= \sum p_i [I_q - I_p] \quad \# I_q - I_p \text{为信息量之差} \\ &= \sum p_i \left[ \log_2\left(\frac{1}{q_i}\right) - \log_2\left(\frac{1}{p_i}\right) \right] \\ &= \sum p_i \log_2\left(\frac{1}{q_i}\right) - \sum p_i \log_2\left(\frac{1}{p_i}\right) \\ &= H(p,q) - H(p) \quad \# 交叉熵减去前者基准分布P的熵 \\ &= \sum p_i \log_2\left(\frac{p_i}{q_i}\right) \end{align*} DKL(p∣∣q)=∑pi[Iq−Ip]#Iq−Ip为信息量之差=∑pi[log2(qi1)−log2(pi1)]=∑pilog2(qi1)−∑pilog2(pi1)=H(p,q)−H(p)#交叉熵减去前者基准分布P的熵=∑pilog2(qipi)
其中交叉熵 H ( p , q ) = ∑ p i I i q = ∑ p i log 2 ( 1 q i ) H(p,q) = \sum p_i I_i^q = \sum p_i \log_2\left(\frac{1}{q_i}\right) H(p,q)=∑piIiq=∑pilog2(qi1)
- 重要性质:
-
恒为正: D ( p ∣ ∣ q ) ≥ 0 D(p \vert \vert q) \geq 0 D(p∣∣q)≥0
由吉布斯不等式可知: D ( p ∣ ∣ q ) ≥ 0 D(p \vert \vert q) \geq 0 D(p∣∣q)≥0;当分布 q q q和分布 p p p完全一样时, D ( p ∣ ∣ q ) = 0 D(p \vert \vert q) = 0 D(p∣∣q)=0
吉布斯不等式说明:若 ∑ i = 1 n p i = ∑ i = 1 n q i = 1 \sum_{i=1}^{n} p_i = \sum_{i=1}^{n} q_i = 1 ∑i=1npi=∑i=1nqi=1,且 p i , q i ∈ ( 0 , 1 ] p_i, q_i \in (0,1] pi,qi∈(0,1],则有:
− ∑ i = 1 n p i log p i ≤ − ∑ i = 1 n p i log q i -\sum_{i=1}^{n} p_i \log p_i \leq -\sum_{i=1}^{n} p_i \log q_i −i=1∑npilogpi≤−i=1∑npilogqi等号成立当且仅当 p i = q i ∀ i p_i = q_i \forall i pi=qi∀i
-
没有'交换律: D ( p ∣ ∣ q ) D(p \vert \vert q) D(p∣∣q)与 D ( q ∣ ∣ p ) D(q \vert \vert p) D(q∣∣p)不一样,
即 D ( p ∣ ∣ q ) ≠ D ( q ∣ ∣ p ) D(p \vert \vert q) \neq D(q \vert \vert p) D(p∣∣q)=D(q∣∣p),可以认为把前面的分别当做真实分布,计算后面的预测分布与之的差异
- D ( p ∣ ∣ q ) D(p \vert \vert q) D(p∣∣q)表示以 p p p为基准(为真实概率分布),估计概率分布 q q q与真实概率分布 p p p之间的差距
- D ( q ∣ ∣ p ) D(q \vert \vert p) D(q∣∣p)表示以 q q q为基准(为真实概率分布),估计概率分布 p p p与真实概率分布 q q q之间的差距
4、交叉熵损失 Cross Entropy Loss
由上可知,KL散度 D ( p ∣ ∣ q ) D(p \vert \vert q) D(p∣∣q)表示预测分布 q q q与真实分布 p p p之间的差距,所以我们可直接将损失函数定义为KL散度。
并且我们希望损失值越小越好,模型的预测分布 q q q与真实分布 p p p完全相同,即:损失函数 L o s s = D ( p ∣ ∣ q ) = 0 Loss = D(p \vert \vert q) = 0 Loss=D(p∣∣q)=0。
损失函数: L o s s = D ( p ∣ ∣ q ) = H ( p , q ) − H ( p ) = ∑ p i log 2 ( 1 q i ) − ∑ p i log 2 ( 1 p i ) (1) Loss = D(p \vert \vert q) = H(p, q) - H(p) = \sum p_i \log_2\left(\frac{1}{q_i}\right) - \sum p_i \log_2\left(\frac{1}{p_i}\right) \tag1 Loss=D(p∣∣q)=H(p,q)−H(p)=∑pilog2(qi1)−∑pilog2(pi1)(1)
下面对公式(1)进行化简
交叉熵损失一般用与分类任务。对于分类问题,真实分布的One-Hot编码是一个单点分布,真实类别的概率为1,其他类别的概率都为0,类似如下:
类别 | class1 | class 2 | class 3 | class 4 |
---|---|---|---|---|
概率 | 0 | 0 | 1 | 0 |
- p c l a s s 1 = p c l a s s 2 = p c l a s s 4 = 0 p_{class1} = p_{class2} = p_{class4} = 0 pclass1=pclass2=pclass4=0,其他类别的概率为零,权重为0就不用算信息量了
- log 2 ( 1 p c l a s s 3 ) = 0 \log_2\left(\frac{1}{p_{class3}}\right) = 0 log2(pclass31)=0,类别3的信息量为0
- 所以, H ( p ) = ∑ p i log 2 ( 1 p i ) = 0 H(p) = \sum p_i \log_2\left(\frac{1}{p_i}\right) = 0 H(p)=∑pilog2(pi1)=0。
损失函数(1)可进一步化简为:
L o s s = D ( p ∣ ∣ q ) = H ( p , q ) − H ( p ) = H ( p , q ) (2) Loss = D(p \vert \vert q) = H(p, q) - H(p) = H(p, q) \tag2 Loss=D(p∣∣q)=H(p,q)−H(p)=H(p,q)(2)
H ( p , q ) H(p, q) H(p,q)是交叉熵,所以损失函数又称为交叉熵损失函数:
C r o s s _ E n t r o p y _ L o s s = H ( p , q ) = − ∑ p i log 2 ( q i ) (3) Cross\_Entropy\_Loss = H(p, q) = -\sum p_i \log_2(q_i) \tag3 Cross_Entropy_Loss=H(p,q)=−∑pilog2(qi)(3)
又因为真实分布为单点分布,真实类别的概率 p c l a s s = 1 p_{class} = 1 pclass=1,其他类别的概率 p c l a s s ‾ = 0 p_{\overline{class}} = 0 pclass=0,所以
C r o s s _ E n t r o p y _ L o s s = H ( p , q ) = − log 2 ( q c l a s s ) Cross\_Entropy\Loss = H(p, q) = -\log_2(q{class}) Cross_Entropy_Loss=H(p,q)=−log2(qclass)
二、交叉熵损失函数
交叉熵损失函数拆解
交叉熵损失多用于多分类任务,下面我们通过拆解交叉熵的公式来理解其作为损失函数的意义。
假设我们在做一个n分类的问题,模型预测的输出结果是 [ x 1 , x 2 , x 3 , ... , x n ] [x_1, x_2, x_3, \dots, x_n] [x1,x2,x3,...,xn],然后,我们选择交叉熵损失函数作为目标函数,通过反向传播调整模型的权重。
交叉熵损失函数的公式:
l o s s ( x , c l a s s ) = − log ( e x [ c l a s s ] ∑ j e x j ) = − x [ c l a s s ] + log ( ∑ j e x j ) \begin{align*} loss(x, class) &= -\log\left(\frac{e^{x_{[class]}}}{\sum_j e^{x_j}}\right) \\ &= -x_{[class]} + \log\left(\sum_j e^{x_j}\right) \end{align*} loss(x,class)=−log(∑jexjex[class])=−x[class]+log(j∑exj)
- x x x是预测结果,是一个向量 x = [ x 1 , x 2 , x 3 , ... , x n ] x = [x_1, x_2, x_3, \dots, x_n] x=[x1,x2,x3,...,xn],其元素个数和类别数一样多。
- c l a s s class class表示这个样本的实际标签,比如,样本实际属于分类2,那么 c l a s s = 2 class = 2 class=2, x [ c l a s s ] x_{[class]} x[class]就是 x 2 x_2 x2,就是取预测结果向量中的第二个元素,即,取其真实分类对应的那个类别的预测值。
接下来,我们来拆解公式,理解公式:
-
首先,交叉熵损失函数中包含了一个最基础的部分:
s o f t m a x ( x i ) = e x i ∑ j = 0 n e x j softmax(x_i) = \frac{e^{x_i}}{\sum_{j = 0}^{n} e^{x_j}} softmax(xi)=∑j=0nexjexisoftmax 将分类的结果做了归一化:
- e x e^x ex的作用是将 x x x转换为非负数
- 通过 softmax 公式 e x i ∑ j = 0 n e x j \frac{e^{x_i}}{\sum_{j = 0}^{n} e^{x_j}} ∑j=0nexjexi计算出该样本被分到类别 i i i的概率,这里所有分类概率相加的总和等于1
-
我们想要使预测结果中,真实分类的那个概率接近100%。我们取出真实类别的那个概率,(下标为class): e x [ c l a s s ] ∑ j = 0 n e x j \frac{e^{x_{[class]}}}{\sum_{j = 0}^{n} e^{x_j}} ∑j=0nexjex[class],我们希望它的值是100%
-
作为损失函数,后面需要参与求导。乘/除法表达式求导比较麻烦,所以最好想办法转化成加/减法表达式。最自然的想法是取对数,把乘除法转化为加减法表达式:
log e x [ c l a s s ] ∑ j = 0 n e x j = log e x [ c l a s s ] − log ∑ j = 0 n e x j \log\frac{e^{x_{[class]}}}{\sum_{j = 0}^{n} e^{x_j}} = \log e^{x_{[class]}} - \log \sum_{j = 0}^{n} e^{x_j} log∑j=0nexjex[class]=logex[class]−logj=0∑nexj- 由于对数单调增,那么,求 e x [ c l a s s ] ∑ j = 0 n e x j \frac{e^{x_{[class]}}}{\sum_{j = 0}^{n} e^{x_j}} ∑j=0nexjex[class]的最大值的问题,可以转化为求 log e x [ c l a s s ] ∑ j = 0 n e x j \log\frac{e^{x_{[class]}}}{\sum_{j = 0}^{n} e^{x_j}} log∑j=0nexjex[class]的最大值的问题。
- e x [ c l a s s ] ∑ j = 0 n e x j \frac{e^{x_{[class]}}}{\sum_{j = 0}^{n} e^{x_j}} ∑j=0nexjex[class]的取值范围是 ( 0 , 1 ) (0, 1) (0,1),最大值为1。取对数之后, log e x [ c l a s s ] ∑ j = 0 n e x j \log\frac{e^{x_{[class]}}}{\sum_{j = 0}^{n} e^{x_j}} log∑j=0nexjex[class]的取值范围为 [ − ∞ , 0 ] [-\infty, 0] [−∞,0],最大值为0
-
作为损失函数的意义是:当预测结果越接近真实值,损失函数的值越接近于0
所以,我们把 log e x [ c l a s s ] ∑ j = 0 n e x j \log\frac{e^{x_{[class]}}}{\sum_{j = 0}^{n} e^{x_j}} log∑j=0nexjex[class]取反之后, − log e x [ c l a s s ] ∑ j = 0 n e x j -\log\frac{e^{x_{[class]}}}{\sum_{j = 0}^{n} e^{x_j}} −log∑j=0nexjex[class]最小值为0
这样就能保证当 e x [ c l a s s ] ∑ j = 0 n e x j \frac{e^{x_{[class]}}}{\sum_{j = 0}^{n} e^{x_j}} ∑j=0nexjex[class]越接近于100%, l o s s = − log ( e x [ c l a s s ] ∑ j = 0 n e x j ) loss = -\log\left(\frac{e^{x_{[class]}}}{\sum_{j = 0}^{n} e^{x_j}}\right) loss=−log(∑j=0nexjex[class])越接近0。
代码实现nn.CrossEntropyLoss
python
nn.CrossEntropyLoss(weight=None,
reduction='mean',
ignore_index=-100)
weight
(optional): 一个张量,用于为每个类别的 loss 设置权值。可以用于处理类别不平衡的情况。- 默认值为
None
weight
必须是float
类型的tensor
,其长度要与类别个数一致,即每一个类别都要设置权重值
l o s s ( x , c l a s s ) = w e i g h t [ c l a s s ] ( − log ( e x [ c l a s s ] ∑ j e x j ) ) loss(x, class) = weight_{[class]} \left(-\log\left(\frac{e^{x_{[class]}}}{\sum_j e^{x_j}}\right)\right) loss(x,class)=weight[class](−log(∑jexjex[class]))
- 默认值为
reduction
(string, optional): 指定损失的计算方式,可选值有:"none"
、"mean"
、"sum"
"none"
:表示不进行任何降维,返回每个样本的损失"mean"
: 表示对参与计算的样本的损失取平均值,("mean"
为默认值)"sum"
: 表示对参与计算的样本的损失求和
ignore_index
(int, optional): 忽略目标中的特定类别索引,不计入损失计算。默认值为-100
代码示例:
假设有4张图片(batch_size=4
),需要把这4张图片分类到5个类别(鸟,狗,猫,汽车,船)上去。经过网络得到的预测结果为predict
,尺寸是[4, 5]
;其真实标签为label
,尺寸是[4]
。接下来使用nn.CrossEntropyLoss()
计算预测结果predict
和真实值label
的交叉熵损失。
python
import torch
import torch.nn as nn
# -----------------------------------------
# 定义数据: batch_size=4; 一共有5个分类
# label.size() : torch.Size([4])
# predict.size(): torch.Size([4, 5])
# -----------------------------------------
torch.manual_seed(100)
predict = torch.rand(4, 5)
label = torch.tensor([4, 3, 3, 2])
print(predict)
print(label)
# -----------------------------------------
# 直接调用函数 nn.CrossEntropyLoss() 计算 Loss
# -----------------------------------------
criterion = nn.CrossEntropyLoss()
loss = criterion(predict, label)
print(loss)

三、二元交叉熵损失函数 Binary Cross Entropy Loss
1、二元交叉熵损失函数
(1)二元交叉熵损失函数(Binary Cross Entropy Loss)适用于二分类问题:样本标签为二元值:0 或 1。
(2)用于将模型预测值和真实值之间的差异转化为一个标量值,从而衡量模型预测的准确性。
计算公式:
L = − 1 N ∑ i = 1 N [ y i log ( y ^ i ) + ( 1 − y i ) log ( 1 − y ^ i ) ] L = -\frac{1}{N} \sum_{i=1}^{N} \left[ y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i) \right] L=−N1i=1∑N[yilog(y^i)+(1−yi)log(1−y^i)]
其中:
- N N N 表示样本数量
- y i y_i yi 表示第 i i i 个样本的真实标签:0 or 1
- y ^ i \hat{y}_i y^i 表示第 i i i 个样本的预测值
如果 y i = 1 y_i = 1 yi=1,则第一项 y i log ( y ^ i ) y_i \log(\hat{y}_i) yilog(y^i) 生效,第二项 ( 1 − y i ) log ( 1 − y ^ i ) (1 - y_i) \log(1 - \hat{y}_i) (1−yi)log(1−y^i) 失效;如果 y i = 0 y_i = 0 yi=0,则第一项 y i log ( y ^ i ) y_i \log(\hat{y}_i) yilog(y^i) 失效,第二项 ( 1 − y i ) log ( 1 − y ^ i ) (1 - y_i) \log(1 - \hat{y}_i) (1−yi)log(1−y^i) 生效。
2、nn.BCELoss() 类
nn.BCELoss()
是 PyTorch 实现的二元交叉熵损失函数,也称为对数损失函数(Log Loss)。
python
torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='mean')
参数说明:
weight
:用于样本加权的权重张量。如果给定,则必须是一维张量,大小等于输入张量的大小。默认值为None
。reduction
:指定如何计算损失值。可选值为'none'
、'mean'
或'sum'
。默认值为'mean'
。
3、使用场景举例
假设有一个二分类任务:判断图片中是否包含猫。该图像的标签值为 0 或 1。我们可以定义一个二元分类模型,用 Sigmoid
输出一个概率值,表示样本属于猫的概率。
python
import torch
import torch.nn as nn
class CatClassifier(nn.Module):
def __init__(self):
super(CatClassifier, self).__init__()
self.fc = nn.Linear(5, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
x = x.view(x.size(0), -1)
x = self.fc(x)
x = self.sigmoid(x)
return x
model = CatClassifier()
criterion = nn.BCELoss()
x = torch.rand((3, 5))
label = torch.tensor([0, 1, 1], dtype=torch.float32)
pred = model(x) # tensor([[0.6140],[0.5350],[0.5852]], grad_fn=<SigmoidBackward0>)
loss = criterion(pred.squeeze(), label)
print(loss)
4、torch.nn.BCEWithLogitsLoss()
与 nn.BCELoss()
的区别
nn.BCELoss()
的输入是二元分类模型的预测值 y ^ \hat{y} y^ 和实际标签 y y y。并且 y ^ \hat{y} y^ 的范围是$[0,1]),因为二元分类模型内部已经对预测结果做了sigmoid
处理。
公式:
n n . B C E L o s s ( ) = − 1 N ∑ i = 1 N [ y i log ( y ^ i ) + ( 1 − y i ) log ( 1 − y ^ i ) ] nn.BCELoss() = -\frac{1}{N} \sum_{i=1}^{N} \left[ y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i) \right] nn.BCELoss()=−N1i=1∑N[yilog(y^i)+(1−yi)log(1−y^i)]torch.nn.BCEWithLogitsLoss()
的输入也是二元分类模型的输出值 z z z 和实际标签 y y y,不同的是输出 z z z 在模型内部没有经过sigmoid
处理,是任意实数。这种情况下,sigmoid
处理就被放到了损失函数中。
所以,torch.nn.BCEWithLogitsLoss()
函数内部的计算过程是先对 z z z 应用sigmoid
函数,将其映射到 [ 0 , 1 ] [0,1] [0,1]范围内,然后再使用二元交叉熵计算预测值和实际标签之间的损失值。
公式:
n n . B C E W i t h L o g i t s L o s s ( ) = − 1 N ∑ i = 1 N [ y i log σ ( z i ) + ( 1 − y i ) log ( 1 − σ ( z i ) ) ] nn.BCEWithLogitsLoss() = -\frac{1}{N} \sum_{i=1}^{N} \left[ y_i \log \sigma(z_i) + (1 - y_i) \log(1 - \sigma(z_i)) \right] nn.BCEWithLogitsLoss()=−N1i=1∑N[yilogσ(zi)+(1−yi)log(1−σ(zi))]- 另外,
torch.nn.BCEWithLogitsLoss()
还支持设置pos_weight
参数,用于处理样本不平衡的问题。而nn.BCELoss()
不支持设置pos_weight
参数。
5、torch.nn.BCEWithLogitsLoss()
类
python
torch.nn.BCEWithLogitsLoss(weight=None,
size_average=None,
reduce=None,
reduction='mean',
pos_weight=None)
参数:
weight
:用于对每个样本的损失值进行加权。默认值为None
。reduction
:指定如何对每个batch
的损失值进行降维。可选值为'none'
、'mean'
和'sum'
。默认值为'mean'
。pos_weight
:用于对正样本的损失值进行加权。可以用于处理样本不平衡的问题。例如,如果正样本比负样本少很多,可以设置pos_weight
为一个较大的值,以提高正样本的权重。默认值为None
。