Pytorch 3.4.2 softmax回归 交叉熵损失函数
交叉熵损失函数
关于信息熵我们已经在上一篇文章中有详细的讲解了"Click here to visit", 对于二分类的问题,信息熵计算公式为:
相对熵(KL散度)
相对熵(relative entropy)又被称为 Kullback-Leibler 散度( Kullback-leibler divergence),是两个概率分布间差异的一种度量, 在信息论中,相对熵等于两个概率分布的信息熵的差值。相对熵的计算公式为:设 \(P(x),Q(x)\)是\(X\)上的两个概率分布, 在离散情况下相对熵的定义分别为:
其中\(P(x)\) 是我们事件真实的概率,\(Q(x)\)使我们预测的概率。比如三类分类问题的标签为\((1,0,0)\) ,预测的标签为\((0.7,0.1,0.2)\)
因此该公式的字面上含义就是真实事件的信息熵
与理论拟合的事件的香农信息量\(Entropy(q_1,q_2,q_3)\)与真实事件的概率的乘积的差的累加。
当p(x)和q(x)相等时相对熵为0,其它情况下大于0。证明如下:
要证明:\(KL(p||q) = \Sigma_{i=1}^{N} P(x_i) \log \frac{P(x)}{Q(x)} ≥ 0\)
即证明:\(\Sigma_{i=1}^{N} p(x_i)\log \frac{Q(x_i)}{P(x_i)} ≤ 0\)
又因为: \(ln(x) ≤ x -1\)(证明省略,可自行导数验证)当且仅当\(x=1\)的时候等号成立
故有: \(\Sigma_{i=1}^{N} P(x_i) \log \frac{Q(x_i)}{P(x_i)} ≤\Sigma_{i=1}^{N}P(x_i) (\frac{Q(x_i)}{P(x_i)} - 1 )\)
当且仅当 \(P(x_i) = Q(x_i)\) 的时候 , \(KL(p||q) = 0\)
交叉熵
除此之外 相对熵还可以写成 :\(Relative Entropy(p,q) = - Entropy(p_1,p_2,p_3) + Entropy(q_1,q_2,q_3)\) 的形式
而等式中的前面的一项:\(-H(P(x))\)就是我们的真实熵 , \(-\Sigma_{i = 1}^{n} p(x_i)\log q(x_i)\) 就是我们要的交叉熵
我们一般使用 \(H(P,Q) = -\Sigma_{i = 1}^{n} p(x_i)\log q(x_i)\) 表示
在机器学习中,使用KL散度就可以评价真实标签与预测标签间的差异,但由于KL散度的第一项是个定值(我们使用one-hot的真实标签进行预测,一般来说都是0),故在优化过程中只关注交叉熵就可以了。一般大多数机器学习算法会选择交叉熵作为损失函数。
Pytorch 实现
在Pytorch中是使用torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')实现的。
假设 我们使用mini_batch gradient decent ,进行求梯度 ,batch_size= 4 ,待分类标签有三个,隐藏层的输出为:
features = torch.tensor([[ 1.1330, -0.6136, -1.3633],
[ 0.4169, 1.2200, -0.2169],
[-0.7368, 0.6024, -1.2759],
[ 0.7969, -1.2343, 0.5294]],requires_grad=True)
经过softmax激活函数之后得到预测值:
output = torch.nn.Softmax(dim=1)(features)
output:
tensor([[0.7957, 0.1387, 0.0656],
[0.2657, 0.5933, 0.1410],
[0.1852, 0.7068, 0.1080],
[0.5273, 0.0692, 0.4035]], grad_fn=<SoftmaxBackward0>)
import torch
import torch.nn as nn
features = torch.tensor([[ 1.1330, -0.6136, -1.3633],
[ 0.4169, 1.2200, -0.2169],
[-0.7368, 0.6024, -1.2759],
[ 0.7969, -1.2343, 0.5294]],requires_grad=True) # 我们定义一个4*3的矩阵,四个样本每个样本三个类别
target = torch.tensor([1,0,2,1])
loss = nn.CrossEntropyLoss()
output = loss(features, target)
# output.backward()
output
输出:
tensor(2.0492, grad_fn=<NllLossBackward0>)
假设我们输入的 \(labels = [1,0,2,1]\) ,\([1,0,2,1]\)指的是第[2个类别,第1个类别,第3个类别,第2个类别](因为Corss Entropy Loss Function 不能够传入 one-hot 形式的数据) 则输出的应该是 (2.409是根据下面的数据计算得到)
softmax函数的输出结果每一行相加为1。 假设这一个mini batch的标签为 [1,0,2,1]
除了 torch.nn.CrossEntropyLoss() 这个函数之外,Pytorch还有另外一个计算交叉熵的函数。 torch.nn.BCELoss()
与之前不同的是该函数主要计算的是 (0-1)分布的交叉熵 因此输出层只有一个神经元(只能输出0或者1)。其公式为:
torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='mean')
import torch
import torch.nn as nn
features = torch.tensor([-0.6168, -0.2976, -0.4502],requires_grad=True)
target = torch.tensor([0.,0.,1.],requires_grad=True)
m = nn.Sigmoid() # 我们分类的是互斥的,要使用Sigmoid函数
loss = nn.BCELoss()
output = loss(m(features),target)
输出:features,output
(tensor([-0.6168, -0.2976, -0.4502], requires_grad=True),
tensor(0.6434, grad_fn=<BinaryCrossEntropyBackward0>))
我们来分析一下计算的过程:
m(features) # tensor([0.3505, 0.4261, 0.3893], grad_fn=<SigmoidBackward0>)
根据二项分布的交叉熵 :
#得证
参考文献/文章:
百度百科-相对熵
简书-学有余力的小心同学
【导数】有趣的lnx≤x-1
posted on 2021-12-24 23:04 YangShusen' 阅读(474) 评论(0) 收藏 举报
浙公网安备 33010602011771号