聊一聊损失函数

前言

损失函数,具体来说就是计算神经网络每次迭代的前向计算结果与真实值的差距,从而指导下一步的训练向正确的方向进行。下面主要介绍一些常见的损失函数:均方差损失函数交叉熵损失函数

均方差损失函数

均方误差损失(Mean Square Error,MSE)又称为二次损失、L2 损失,常用于回归预测任务中。均方误差函数通过计算预测值和实际值之间距离(即误差)的平方来衡量模型优劣。即预测值和真实值越接近,两者的均方差就越小。

均方差函数常用于线性回归(linear regrWession),即函数拟合(function fitting)。公式如下:

loss=12(ay)2(单样本)loss = {1 \over 2}(a-y)^2 \tag{单样本}

J=12mi=1m(aiyi)2(多样本)J=\frac{1}{2m} \sum_{i=1}^m (a_i-y_i)^2 \tag{多样本}

均方差函数比较简单,也较为常见,这里就不多说了。

交叉熵损失函数

交叉熵(Cross Entropy)是 Shannon 信息论中一个重要概念,主要用于度量两个概率分布间的差异性信息。在信息论中,交叉熵是表示两个概率分布 p,qp,q 的差异,其中 pp 表示真实分布,qq 表示预测分布,那么 H(p,q)H(p,q) 就称为交叉熵:

H(p,q)=ipiln1qi=ipilnqiH(p,q)=\sum_i p_i \cdot \ln \frac{1}{q_i} = -\sum_i p_i \ln q_i

交叉熵可在神经网络中作为损失函数,pp 表示真实标记的分布,qq 则为训练后的模型的预测标记分布,交叉熵损失函数可以衡量 ppqq 的相似性。

交叉熵函数常用于逻辑回归(logistic regression),也就是分类(classification)。

信息量

信息量来衡量一个事件的不确定性,一个事件发生的概率越大,不确定性越小,则其携带的信息量就越小。在信息论中,可以通过如下方式表示:

I(xj)=ln(p(xj))I(x_j) = -\ln(p(x_j))

其中xjx_j表示一个事件,p(xj)p(x_j)表示xjx_j发生的概率。

举个例子,对于下面这三个事件,可以通过概率计算其信息量:

事件编号 事件 概率 信息量
x1x_1 优秀 p=0.7p=0.7 I=ln(0.7)=0.36I=-\ln(0.7)=0.36
x2x_2 及格 p=0.2p=0.2 I=ln(0.2)=1.61I=-\ln(0.2)=1.61
x3x_3 不及格 p=0.1p=0.1 I=ln(0.1)=2.30I=-\ln(0.1)=2.30

事件发生的概率越小,其信息量越大。

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

H(p)=jnp(xj)ln(p(xj))H(p)=-\sum_j^n p(x_j)\ln(p(x_j))

其中p(xj)p(x_j)表示xjx_j发生的概率,ln(p(xj))-\ln(p(x_j))表示事件的信息量。

信息量是衡量某个事件的不确定性,而熵是衡量一个系统(所有事件)的不确定性。

对于上面的例子,我们可以计算其熵:

H(p)=[p(x1)lnp(x1)+p(x2)lnp(x2)+p(x3)lnp(x3)]=0.7×0.36+0.2×1.61+0.1×2.30=0.804\begin{aligned}H(p) &= -[p(x_1)\ln p(x_1) + p(x_2)\ln p(x_2) + p(x_3)\ln p(x_3)] \\ &= 0.7 \times 0.36 + 0.2 \times 1.61 + 0.1 \times 2.30 \\ &= 0.804 \end{aligned}

相对熵(KL 散度)

相对熵也称为 KL 散度(Kullback-Leibler divergence),表示同一个随机变量的两个不同分布间的距离,相当于信息论范畴的均方差。

p(x),q(x)p(x),q(x)分别是随机变量xx的两个概率分布,则ppqq的相对熵计算如下:

DKL(pq)=j=1np(xj)lnp(xj)q(xj)D_{KL}(p \Vert q) = \sum_{j=1}^n p(x_j) \ln \frac{p(x_j)}{q(x_j)}

其中nn为事件的所有可能性。相对熵DD的值越小,表示两个分布越接近。在实际应用中,假如p(x)p(x)是目标真实的分布,而q(x)q(x)是预测得来的分布,为了让这两个分布尽可能的相同的,就需要最小化 KL 散度。

交叉熵

将上述公式变形:

DKL(pq)=j=1np(xj)lnp(xj)q(xj)=j=1np(xj)lnp(xj)j=1np(xj)lnq(xj)=H(p(x))+H(p,q)\begin{aligned} D_{KL}(p \Vert q) &= \sum_{j=1}^n p(x_j) \ln \frac{p(x_j)}{q(x_j)} \\ &= \sum_{j=1}^n p(x_j) \ln p(x_j) - \sum_{j=1}^n p(x_j) \ln q(x_j) \\ &= -H(p(x)) + H(p,q) \end{aligned}

其中,等式的前一部分就是pp的熵,后一部分就是交叉熵:

H(p,q)=j=1np(xj)lnq(xj)H(p,q) = -\sum_{j=1}^n p(x_j) \ln q(x_j)

在机器学习中,我们需要评估标签值yy和预测值aa之间的差距,就可以计算DKL(pq)D_{KL}(p \Vert q),由于H(y)H(y)不变,因此在优化过程中只需要考虑交叉熵即可。对于单样本计算如下:

loss=j=1nyjlnajloss = -\sum_{j=1}^n y_j \ln a_j

对于批量样本的交叉熵计算如下:

J=i=1mj=1nyijlnaiJ= -\sum_{i=1}^m\sum_{j=1}^n y_{ij} \ln a_{i}

其中mm为样本数,nn为分类数。

二分类问题交叉熵

在二分的情况下,通常使用sigmoid 将输出映射为正样本的概率,对于每个类别我们的预测的到的概率为aa1a1-a,所以交叉熵可以简化为:

loss=[ylna+(1y)ln(1a)]loss = -[y\ln a + (1-y)\ln(1-a)]

二分类对于批量样本的交叉熵计算公式:

J=i=1m[yilnai+(1yi)ln(1ai)]J = -\sum_{i=1}^m [y_i\ln a_i + (1-y_i)\ln(1-a_i)]

简单分析一下公式,可以发现,当y=1y=1时为正样本,loss=ln(a)loss=-\ln(a);当y=0y=0时为负样本,loss=ln(1a)loss=-\ln(1-a)

事件编号 预测值aa 真实值yy
x1x_1 0.6 1
x2x_2 0.7 1

举个例子,对于上面的情况,我们分别计算其交叉熵损失:

loss1=(1×ln0.6+(11)×ln(10.6))=0.51loss_1 = -(1 \times \ln 0.6 + (1-1) \times \ln (1-0.6)) = 0.51

loss2=(1×ln0.7+(11)×ln(10.7))=0.36loss_2 = -(1 \times \ln 0.7 + (1-1) \times \ln (1-0.7)) = 0.36

计算得到loss1>loss2loss_1 > loss_2,相应的loss2loss_2反向传播的力度也会小。

多分类问题交叉熵

多分类问题也是类似的,考虑下面的优秀、及格、不及格分类:

事件编号 p(x1)=优秀p(x_1)=优秀 p(x1)=及格p(x_1)=及格 p(x1)=不及格p(x_1)=不及格 真实值yy
x1x_1 0.2 0.5 0.3 不及格
x2x_2 0.2 0.2 0.6 不及格

举个例子,对于上面的情况,我们分别计算其交叉熵损失:

loss1=(0×ln0.2+0×ln0.5+1×ln0.3)=1.2loss_1 = -(0 \times \ln 0.2 + 0 \times \ln 0.5 + 1 \times \ln 0.3) = 1.2

loss2=(0×ln0.2+0×ln0.2+1×ln0.6)=0.51loss_2 = -(0 \times \ln 0.2 + 0 \times \ln 0.2 + 1 \times \ln 0.6) = 0.51

计算得到loss1>loss2loss_1 > loss_2,相应的loss2loss_2反向传播的力度也会小。

PyTorch 实现

在 PyTorch 中,常用的损失函数我们可以直接调用:

  • nn.MSELoss()
  • nn.CrossEntropyLoss()

但有时我们会需要自定义损失函数,这时我们可以将其当作神经网络的一层来对待,同样地,我们的损失函数类就需要继承自nn.Module类。

1
2
3
4
5
6
7
8
9
10
import torch
import torch.nn as nn

class myLoss(nn.Module):
def __init__(self,parameters)
self.params = self.parameters

def forward(self)
loss = cal_loss(self.params)
return loss

参考资料