交叉熵nn.CrossEntropyLoss()和nn.BCELoss()

交叉熵

用于判定实际的输出(概率)和期望的输出(概率)的接近程度(距离)。

交叉熵的值越小,两个概率分布就越接近。

相关概念

信息量:用于衡量一个事件的不确定性。一个事件发生的概率越大,不确定性越小,则它所携带的信息量就越小。如“骰子这次投出的点数小于10”这句话本身不含信息量。

假设 x x x是一个离散型随机变量,其取值集合为X,概率分布函数为 p ( x ) = P ( X = x ) , x ∈ X p(x)=P(X=x),x\in X p(x)=P(X=x),xX ,我们定义事件 X = x 0 X=x_0 X=x0 的信息量为: I ( x 0 ) = − log ⁡ ( p ( x 0 ) ) I(x_0)=−\operatorname{log}(p(x_0)) I(x0)=log(p(x0))

:用来衡量一个系统的混乱程度的,代表一个系统中信息量的总和;信息量总和越大,表明这个系统不确定性就越大。

计算公式

假设概率分布p为期望输出,概率分布q为实际输出,H(p, q)为交叉熵,则:

H ( p , q ) = − Σ x ( p ( x ) log ⁡ ( q ( x ) ) + ( 1 − p ( x ) ) log ⁡ ( 1 − q ( x ) ) ) H(p, q)=-\Sigma_x (p(x)\operatorname{log}(q(x))+(1-p(x))\operatorname{log}(1-q(x))) H(p,q)=Σx(p(x)log(q(x))+(1p(x))log(1q(x)))

torch.nn.CrossEntropyLoss()

torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=- 100, reduce=None, reduction='mean', label_smoothing=0.0)
计算公式

在pytorch中,使用了交叉熵的一半进行计算[不影响结果大小的比较]: − Σ x p ( x ) log ⁡ q ( x ) -\Sigma_x p(x)\operatorname{log}q(x) Σxp(x)logq(x)
l o s s ( y ^ , t ) = − Σ i w i ( y i log ⁡ ( y ^ i ) ) n loss(\hat{y},t)=-\frac{\Sigma_i w_i (y_i\operatorname{log}(\hat{y}_i))}{n} loss(y^,t)=nΣiwi(yilog(y^i))

其中 y ^ \hat{y} y^是网络的输出向量,t是其对应的真实标签(int),n为batch_num

交叉熵损失函数专门用于处理one-hot型 (prediction) y_hat值对应的int型 (label) 目标值t多分类问题。

意思是,一个设计良好的模型经过训练后,理想状态下,最终结果应为y_hat[i==t]=1,y_hat[i!=t]=0

从数学的角度理解交叉熵损失函数

对于分类问题来说:

one-hot型prediction: y ^ \hat{y} y^

int型label: t t t,转换为one-hot型label: y y y,则有 y t = 1 y_t=1 yt=1,向量y的其余元素为0

从目前预测出的情况中获得期望的label输出的可能性是: Π i y ^ i y i \Pi_i\hat{y}_i^{y_i} Πiy^iyi

  1. 我们希望这个可能性越大越好
  2. 为了计算方便(将连乘转换为累加)且保证函数的单调性,我们取个log

我们求的是: arg ⁡ max ⁡ Σ i y i log ⁡ y ^ i = arg ⁡ min ⁡ − Σ i y i log ⁡ y ^ i \arg \max{\Sigma_i y_i \operatorname{log}\hat{y}_i}=\arg \min{-\Sigma_i y_i \operatorname{log}\hat{y}_i} argmaxΣiyilogy^i=argminΣiyilogy^i

又因为由int型label转化成的one-hot型向量只有一个元素值为1,其余元素值都为0

所以上式可化简为: arg ⁡ min ⁡ − log ⁡ y ^ t \arg \min{-\operatorname{log}\hat{y}_t} argminlogy^t

实现原理

这个损失函数其实是结合nn.LogSoftmax()nn.NLLLoss()两个函数

Softmax是让数值之和为1,符合概率分布的特性

nn.NLLLoss()(input, target)
# 在分类问题上,shape如下:
input: (batch_num, classes_num)
target: (batches_num)

# 有时我们想对图片做nn.CrossEntropyLoss(),shape如下:
# 如果这是一张2D图片,shape为(d1, d2)
# 比如说,我们去学一个图片pixel的二分类问题(该pixel是否属于Edge)
input: (batch_num, class_num, d1, d2)
target: (batches_num, d1, d2)
  1. 将int型target转化为one-hot编码y
  2. − Σ i y i × input i -\Sigma_i y_i\times \text{input}_i Σiyi×inputi
例子

one-hot型prediction: predition=[0.1, 0.1, 0.8]

int型label: 2 先转化为one-hot类型 => label=[0, 0, 1]

交叉熵nn.CrossEntropyLoss()和nn.BCELoss()_第1张图片

Loss = − ( 0 ∗ log ⁡ 0.1 + 0 ∗ log ⁡ 0.1 + 1 ∗ log ⁡ 0.8 ) = − 1 ∗ log ⁡ 0.8 \text{Loss}=-(0*\operatorname{log}0.1+0*\operatorname{log}0.1+1*\operatorname{log}0.8)=-1*\operatorname{log}0.8 Loss=(0log0.1+0log0.1+1log0.8)=1log0.8

# # 用代码细写出这个等价形式
import torch.nn as nn

input = torch.rand(3, 3) # predition
target = torch.tensor([0, 1, 2]) # shape=(3) # label

# 直接用nn.CrossEntropyLoss函数
criterion_entropy = nn.CrossEntropyLoss()
loss = criterion_entropy(input, target)

# 拆解成分步计算的形式
input = nn.LogSoftmax(dim=1)(input)
loss = nn.NLLLoss()(input, target)

torch.nn.BCELoss

torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='mean')
计算公式

在pytorch中,使用了交叉熵进行计算: − Σ x ( p ( x ) log ⁡ ( q ( x ) ) + ( 1 − p ( x ) ) log ⁡ ( 1 − q ( x ) ) ) -\Sigma_x (p(x)\operatorname{log}(q(x))+(1-p(x))\operatorname{log}(1-q(x))) Σx(p(x)log(q(x))+(1p(x))log(1q(x)))
l o s s ( y ^ , t ) = − Σ i w i [ y i log ⁡ ( y ^ i ) + ( 1 − y i ) log ⁡ ( 1 − y ^ i ) ] n loss(\hat{y},t)=-\frac{\Sigma_i w_i [y_i\operatorname{log}(\hat{y}_i)+(1-y_i)\operatorname{log}(1-\hat{y}_i)]}{n} loss(y^,t)=nΣiwi[yilog(y^i)+(1yi)log(1y^i)]

其中 y ^ \hat{y} y^是网络的输出向量,t是其对应的真实标签(int),n=batch_num

你可能感兴趣的:(数学,深度学习,pytorch,深度学习,人工智能)