平均绝对误差(MAE),用于回归模型
对于包含 N N N个样本的batch数据 D ( x , y ) D(x, y) D(x,y), x x x为神经网络的输出, y y y是真实的得分, x x x与 y y y同维度。
第 n n n个样本的损失值 l n l_{n} ln计算如下:
l n = ∣ x n − y n ∣ l_{n}=\left|x_{n}-y_{n}\right| ln=∣xn−yn∣
其中, y n y_{n} yn代表第 n n n样本的真实得分,可能对应一个值,也可能多个值,代表样本不同方面的得分,所以 l n l_{n} ln可能是一个值,也可能是一个向量。
class L1Loss(_Loss):
def __init__(self, size_average=None, reduce=None, reduction='mean'):
super(L1Loss, self).__init__(size_average, reduce, reduction)
def forward(self, input, target):
return F.l1_loss(input, target, reduction=self.reduction)
pytorch中通过torch.nn.L1Loss
类实现,也可以直接调用F.l1_loss
函数,代码中的size_average
与reduce
已经弃用。reduction有三种取值mean
, sum
, none
,对应不同的返回 ℓ ( x , y ) \ell(x, y) ℓ(x,y)。 默认为mean
,对 L L L中所有元素求平均,对应于一般情况下的 l o s s loss loss的计算。
L = { l 1 , … , l N } L=\left\{l_{1}, \ldots, l_{N}\right\} L={l1,…,lN}
ℓ ( x , y ) = { L , if reduction = ’none’ mean ( L ) , if reduction = ’mean’ sum ( L ) , if reduction = ’sum’ \ell(x, y)=\left\{\begin{array}{ll}\operatorname L, & \text { if reduction }=\text { 'none' } \\ \operatorname{mean}(L), & \text { if reduction }=\text { 'mean' } \\ \operatorname{sum}(L), & \text { if reduction }=\text { 'sum' }\end{array} \right. ℓ(x,y)=⎩⎨⎧L,mean(L),sum(L), if reduction = ’none’ if reduction = ’mean’ if reduction = ’sum’
均方误差(MSE),用于回归模型
对于包含 N N N个样本的batch数据 D ( x , y ) D(x, y) D(x,y), x x x为神经网络的输出, y y y是真实的得分。
第 n n n个样本的损失值 l n l_{n} ln计算如下:
l n = ( x n − y n ) 2 l_{n}=\left(x_{n}-y_{n}\right)^{2} ln=(xn−yn)2
其中, y n y_{n} yn代表第 n n n样本的真实得分,可能对应一个值,也可能多个值,代表样本不同方面的得分,所以 l n l_{n} ln可能是一个值,也可能是一个向量。
class MSELoss(_Loss):
def __init__(self, size_average=None, reduce=None, reduction='mean'):
super(MSELoss, self).__init__(size_average, reduce, reduction)
def forward(self, input, target):
return F.mse_loss(input, target, reduction=self.reduction)
pytorch中通过torch.nn.MSELoss
类实现,也可以直接调用F.mse_loss
函数。代码中的size_average
与reduce
已经弃用。reduction有三种取值mean
, sum
, none
,对应不同的返回 ℓ ( x , y ) \ell(x, y) ℓ(x,y)。默认为mean
,对 L L L中所有元素求平均,对应于一般情况下的 l o s s loss loss的计算。
L = { l 1 , … , l N } L=\left\{l_{1}, \ldots, l_{N}\right\} L={l1,…,lN}
ℓ ( x , y ) = { L , if reduction = ’none’ mean ( L ) , if reduction = ’mean’ sum ( L ) , if reduction = ’sum’ \ell(x, y)=\left\{\begin{array}{ll}\operatorname L, & \text { if reduction }=\text { 'none' } \\ \operatorname{mean}(L), & \text { if reduction }=\text { 'mean' } \\ \operatorname{sum}(L), & \text { if reduction }=\text { 'sum' }\end{array} \right. ℓ(x,y)=⎩⎨⎧L,mean(L),sum(L), if reduction = ’none’ if reduction = ’mean’ if reduction = ’sum’
分段使用均方误差和平均绝对误差,用于回归模型
对于包含 N N N个样本的batch数据 D ( x , y ) D(x, y) D(x,y), x x x为神经网络的输出, y y y是真实的得分。
第 n n n个样本的损失值 l n l_{n} ln计算如下:
l n = { 0.5 ( x n − y n ) 2 / beta , if ∣ x n − y n ∣ < beta ∣ x n − y n ∣ − 0.5 ∗ beta , otherwise l_{n}=\left\{\begin{array}{ll}0.5\left(x_{n}-y_{n}\right)^{2} / \text { beta }, & \text { if }\left|x_{n}-y_{n}\right|<\text { beta } \\ \left|x_{n}-y_{n}\right|-0.5 * \text { beta }, & \text { otherwise }\end{array}\right. ln={0.5(xn−yn)2/ beta ,∣xn−yn∣−0.5∗ beta , if ∣xn−yn∣< beta otherwise
其中, y n y_{n} yn代表第 n n n样本的真实得分,可能对应一个值,也可能多个值,代表样本不同方面的得分,所以 l n l_{n} ln可能是一个值,也可能是一个向量。
相比平均绝对误差,SmoothL1Loss平滑了 ∣ x n − y n ∣ \left|x_{n}-y_{n}\right| ∣xn−yn∣趋近于0时的误差。相比均方误差函数,SmoothL1Loss对离群点更不敏感。在一定程度上可以防止梯度爆炸问题。Fast R-CNN论文有详细论述。
class SmoothL1Loss(_Loss):
def __init__(self, size_average=None, reduce=None, reduction: str = 'mean', beta: float = 1.0) -> None:
super(SmoothL1Loss, self).__init__(size_average, reduce, reduction)
self.beta = beta
def forward(self, input: Tensor, target: Tensor) -> Tensor:
return F.smooth_l1_loss(input, target, reduction=self.reduction, beta=self.beta)
pytorch中通过torch.nn.SmoothL1Loss
类实现,也可以直接调用F.smooth_l1_loss
函数。代码中的size_average
与reduce
已经弃用。reduction有三种取值mean
, sum
, none
,对应不同的返回 ℓ ( x , y ) \ell(x, y) ℓ(x,y)。默认为mean
,对 L L L中所有元素求平均,对应于一般情况下的 l o s s loss loss的计算。
L = { l 1 , … , l N } L=\left\{l_{1}, \ldots, l_{N}\right\} L={l1,…,lN}
ℓ ( x , y ) = { L , if reduction = ’none’ mean ( L ) , if reduction = ’mean’ sum ( L ) , if reduction = ’sum’ \ell(x, y)=\left\{\begin{array}{ll}\operatorname L, & \text { if reduction }=\text { 'none' } \\ \operatorname{mean}(L), & \text { if reduction }=\text { 'mean' } \\ \operatorname{sum}(L), & \text { if reduction }=\text { 'sum' }\end{array} \right. ℓ(x,y)=⎩⎨⎧L,mean(L),sum(L), if reduction = ’none’ if reduction = ’mean’ if reduction = ’sum’
参数 b e t a > = 0 beta>=0 beta>=0,默认为1
分段使用均方误差和平均绝对误差,用于回归模型
对于包含 N N N个样本的batch数据 D ( x , y ) D(x, y) D(x,y), x x x为神经网络的输出, y y y是真实的得分。
第 n n n个样本的损失值 l n l_{n} ln计算如下:
l n = { 0.5 ( x n − y n ) 2 , if ∣ x n − y n ∣ < beta beta ∗ ( ∣ x n − y n ∣ − 0.5 ∗ beta ) , otherwise l_{n}=\left\{\begin{array}{ll}0.5\left(x_{n}-y_{n}\right)^{2}, & \text { if }\left|x_{n}-y_{n}\right|<\text { beta } \\ \text { beta }*(\left|x_{n}-y_{n}\right|-0.5 * \text { beta }), & \text { otherwise }\end{array}\right. ln={0.5(xn−yn)2, beta ∗(∣xn−yn∣−0.5∗ beta ), if ∣xn−yn∣< beta otherwise
对比SmoothL1Loss
和HuberLoss
公式可知, HuberLoss = beta ∗ SmoothL1Loss \text {HuberLoss}= \text {beta}* \text {SmoothL1Loss} HuberLoss=beta∗SmoothL1Loss,两者有如下区别:
SmoothL1Loss
收敛于L1Loss
, HuberLoss
收敛于常数0SmoothL1Loss
收敛于常数0,HuberLoss
收敛于MSELoss
SmoothL1Loss
中平均绝对误差段的斜率恒定为1;而HuberLos
中平均绝对误差段的斜率是 b e t a beta betaSmoothL1Loss
例子:
import torch
import torch.nn as nn
import math
def validate_loss(output, target, beta):
val = 0
for li_x, li_y in zip(output, target):
for i, xy in enumerate(zip(li_x, li_y)):
x, y = xy
if math.fabs(x - y) < beta:
loss_val = 0.5 * math.pow(x - y, 2) / beta
else:
loss_val = math.fabs(x - y) - 0.5 * beta
val += loss_val
return val / output.nelement()
beta = 1
loss_fct = nn.SmoothL1Loss(reduction="mean", beta=beta)
input_src = torch.Tensor([[0.8, 0.8], [0.9, 0.9], [0.3, 0.3]])
target = torch.Tensor([[0.6, 0.6], [0.7, 0.8], [0.4, 0.5]])
print(input_src.size())
print(target.size())
loss = loss_fct(input_src, target)
print(loss.item())
validate = validate_loss(input_src, target, beta)
print(validate)
loss_fct = nn.SmoothL1Loss(reduction="none", beta=beta)
loss = loss_fct(input_src, target)
print(loss)
输出结果:
torch.Size([3, 2])
torch.Size([3, 2])
0.01499999687075615
0.014999997715155441
tensor([[0.0200, 0.0200],
[0.0200, 0.0050],
[0.0050, 0.0200]])