loss函数之MultiMarginLoss, MultiLabelMarginLoss

MultiMarginLoss

多分类合页损失函数(hinge loss),对于一个样本不是考虑样本输出与真实类别之间的误差,而是考虑对应真实类别与其他类别之间的误差

对于包含 N N N个样本的batch数据 D ( x , y ) D(x, y) D(x,y) x x x为神经网络的输出, y y y是真实的类别标签,假设类别数为 C C C, 0 ≤ y n ≤ C − 1 0 \leq y_{n} \leq C-1 0ynC1

n n n个样本的损失值 l n l_{n} ln计算如下:

l n = 1 C ∑ i = 0 & i ≠ y n C − 1 max ⁡ ( 0 , margin ⁡ − x n [ y n ] + x n [ i ] ) p l_{n}=\frac1{C}{ \sum_{i=0 \&i \neq y_{n}}^{C-1} \max (0, \operatorname{margin}-x_{n}[y_{n}]+x_{n}[i])^{p}} ln=C1i=0&i=ynC1max(0,marginxn[yn]+xn[i])p

为了处理多个类别之间的样本不平衡问题,对于每一类可传入相应的权值 w w w

l n = 1 C ∑ i = 0 & i ≠ y n C − 1 max ⁡ ( 0 , w [ y n ] ( margin ⁡ − x n [ y n ] + x n [ i ] ) ) p l_{n}=\frac1{C}{ \sum_{i=0 \&i \neq y_{n}}^{C-1} \max (0, w[y_{n}](\operatorname{margin}-x_{n}[y_{n}]+x_{n}[i]))^{p}} ln=C1i=0&i=ynC1max(0,w[yn](marginxn[yn]+xn[i]))p

p = 1 p=1 p=1, 由以上公式可知:

(1) 当 m a r g i n − x n [ y n ] + x n [ i ] < 0 {margin}-x_{n}[y_{n}]+x_{n}[i]<0 marginxn[yn]+xn[i]<0时,即 m a r g i n + x n [ i ] < x n [ y n ] {margin}+x_{n}[i]<x_{n}[y_{n}] margin+xn[i]<xn[yn], 该样本被误认为类别 i i i l o s s loss loss为0。

此时,样本预测为正确类别 y n y_{n} yn的概率大于预测为 i i i类别的概率,并且差值大于 m a r g i n margin margin。 这样的样本被认为是易分类样本,直接忽略其带来的误差。

(2)当 m a r g i n − x n [ y n ] + x n [ i ] > 0 {margin}-x_{n}[y_{n}]+x_{n}[i]>0 marginxn[yn]+xn[i]>0时,该样本被误认为类别 i i i l o s s loss loss m a r g i n − x n [ y n ] + x n [ i ] {margin}-x_{n}[y_{n}]+x_{n}[i] marginxn[yn]+xn[i], 分为两种情况:

  • m a r g i n + x n [ i ] > x n [ y n ] > x n [ i ] {margin}+x_{n}[i]>x_{n}[y_{n}]>x_{n}[i] margin+xn[i]>xn[yn]>xn[i],对应难分类样本,样本被误认为类别 i i i的概率值小于正确类别 y n y_{n} yn,但是两者的差值小于 m a r g i n margin margin

  • m a r g i n + x n [ i ] > x n [ i ] > x n [ y n ] {margin}+x_{n}[i]>x_{n}[i]>x_{n}[y_{n}] margin+xn[i]>xn[i]>xn[yn],对应非常难分类样本,容易被分为类别 i i i

class MultiMarginLoss(_WeightedLoss):
    __constants__ = ['p', 'margin', 'weight', 'reduction']
    def __init__(self, p=1, margin=1., weight=None, size_average=None,
                 reduce=None, reduction='mean'):
        super(MultiMarginLoss, self).__init__(weight, size_average, reduce, reduction)
        if p != 1 and p != 2:
            raise ValueError("only p == 1 and p == 2 supported")
        assert weight is None or weight.dim() == 1
        self.p = p
        self.margin = margin
    def forward(self, input, target):
        return F.multi_margin_loss(input, target, p=self.p, margin=self.margin,
                                   weight=self.weight, reduction=self.reduction)

pytorch中通过torch.nn.MultiMarginLoss类实现,也可以直接调用F.multi_margin_loss 函数,代码中的weight即是 w w wsize_averagereduce已经弃用。reduction有三种取值mean, sum, none,对应不同的返回 ℓ ( x , y ) \ell(x, y) (x,y). 默认为mean,对应于一般情况下整体 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’  1 N ∑ n = 1 N l n ,  if reduction  =  ’mean’  ∑ n = 1 N l n  if reduction  =  ’sum’  \ell(x, y)=\left\{\begin{array}{ll}\operatorname L, & \text { if reduction }=\text { 'none' } \\ \frac1{N}\sum_{n=1}^{N} l_{n}, & \text { if reduction }=\text { 'mean' } \\ \sum_{n=1}^{N} l_{n} & \text { if reduction }=\text { 'sum' }\end{array} \right. (x,y)=L,N1n=1Nln,n=1Nln if reduction = ’none’  if reduction = ’mean’  if reduction = ’sum’ 

p p p 值默认为1,另外可设为2,其他数值不支持。 m a r g i n margin margin也是人为设定的值,默认为1

例子:

x = torch.FloatTensor([[0.1, 0.2, 0.4, 0.8], [0.1, 0.2, 0.4, 0.8]])
print(x.size())
y = torch.LongTensor([3, 3])
print(y.size())

loss = nn.MultiMarginLoss(reduction="none")
loss_val = loss(x, y)
print(loss_val)

loss = nn.MultiMarginLoss(reduction="sum")
loss_val = loss(x, y)
print(loss_val.item())
print(loss_val.item() / x.size(0))
#验证
print(1 / 2 * 1 / 4 * ((1 - 0.8 + 0.1) + (1 - 0.8 + 0.2) + (1 - 0.8 + 0.4) +
                       (1 - 0.8 + 0.1) + (1 - 0.8 + 0.2) + (1 - 0.8 + 0.4)))

运行结果:

torch.Size([2, 4])
torch.Size([2])
tensor([0.3250, 0.3250])
0.6499999761581421
0.32499998807907104
0.32499999999999996

MultiLabelMarginLoss

多标签合页损失(hinge loss),上述的多分类合页损失MultiMarginLoss应用于一个样本仅仅对应一个真实类别的情况。而MultiLabelMarginLoss应用于一个样本对应多个真实类别的情况,但是类别总数不超过 C C C

对于包含 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 = 1 C ∑ j ∈ y n ∑ i ∉ y n max ⁡ ( 0 , 1 − x n [ j ] + x n [ i ] ) l_{n}=\frac1{C}{ \sum_{j \in y_{n}}\sum_{i \notin y_{n}} \max (0, 1-x_{n}[j]+x_{n}[i])} ln=C1jyni/ynmax(0,1xn[j]+xn[i])

其中,每个样本对应的类别数量不同,只考虑 y n y_{n} yn中数值 − 1 -1 1之前的连续类别。 若某个样本对应的 y n = [ 2 , 3 , − 1 , 0 ] y_{n}=[2,3,-1,0] yn=[2,3,1,0],表示总的类别有四个,而2和3类别属于该样本,0和1类别不属于该样本。 y n = [ 2 , 3 , − 1 , 0 ] y_{n}=[2,3,-1,0] yn=[2,3,1,0] y n = [ 3 , 2 , − 1 , 0 ] y_{n}=[3,2,-1,0] yn=[3,2,1,0]两种表示相同。

class MultiLabelMarginLoss(_Loss):
    __constants__ = ['reduction']
    def __init__(self, size_average=None, reduce=None, reduction='mean'):
        super(MultiLabelMarginLoss, self).__init__(size_average, reduce, reduction)
    def forward(self, input, target):
        return F.multilabel_margin_loss(input, target, reduction=self.reduction)

pytorch中通过torch.nn.MultiLabelMarginLoss类实现,也可以直接调用F.multilabel_margin_loss 函数,代码中的weight即是 w w wsize_averagereduce已经弃用。reduction有三种取值mean, sum, none,对应不同的返回 ℓ ( x , y ) \ell(x, y) (x,y). 默认为mean,对应于一般情况下整体 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’  1 N ∑ n = 1 N l n ,  if reduction  =  ’mean’  ∑ n = 1 N l n  if reduction  =  ’sum’  \ell(x, y)=\left\{\begin{array}{ll}\operatorname L, & \text { if reduction }=\text { 'none' } \\ \frac1{N}\sum_{n=1}^{N} l_{n}, & \text { if reduction }=\text { 'mean' } \\ \sum_{n=1}^{N} l_{n} & \text { if reduction }=\text { 'sum' }\end{array} \right. (x,y)=L,N1n=1Nln,n=1Nln if reduction = ’none’  if reduction = ’mean’  if reduction = ’sum’ 

例子:

loss = nn.MultiLabelMarginLoss()
x = torch.FloatTensor([[0.1, 0.2, 0.4, 0.8]])
y = torch.LongTensor([[3, 0, -1, 1]])
print(x.size())
print(y.size())

loss_val = loss(x, y)
print(loss_val.item())
# 验证
print(0.25 * ((1 - (0.8 - 0.2)) + (1 - (0.8 - 0.4)) + (1 - (0.1 - 0.2)) + (1 - (0.1 - 0.4))))

y = torch.LongTensor([[3, 0, 1, -1]])
loss_val = loss(x, y)
print(loss_val.item())
# 验证
print(0.25 * ((1 - (0.8 - 0.4)) + (1 - (0.1 - 0.4)) + (1 - (0.2 - 0.4))))

y = torch.LongTensor([[3, 0, 2, 1]])
loss_val = loss(x, y)
print(loss_val.item())
# 如果包含全部的类别,loss为0?

输出结果:

torch.Size([1, 4])
torch.Size([1, 4])
0.8499999642372131
0.8500000000000001
0.7749999761581421
0.7749999999999999
0.0

但是,如果样本包含全部的类别,对应的loss就为0。这样定义loss不是很奇怪嘛。

  • 11
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
val_loss函数是指用于评估模型在验证集上的损失函数。在机器学习中,我们通常将数据集划分为训练集和验证集,用训练集训练模型,然后用验证集验证模型的性能。val_loss函数被用来衡量模型预测结果与验证集标签之间的差异程度。 val_loss函数的代码实现通常与模型训练过程中的损失函数的代码实现类似。在训练过程中,模型会根据训练集的输入和标签生成预测结果,并计算与标签之间的差异,即损失值。同样地,在验证过程中,模型会根据验证集的输入生成预测结果,并计算与验证集的标签之间的差异,这就是val_loss函数的计算方式。 具体的val_loss函数的代码实现可能会根据具体的机器学习框架和任务而有所不同。一般来说,val_loss函数的计算会涉及到模型的预测结果和验证集标签的对比,计算它们之间的差异,并根据差异的大小来评估模型在验证集上的性能。 val_loss函数的数值越小,表示模型在验证集上的性能越好。在训练过程中,我们通常会监控val_loss函数的数值变化,以判断模型是否出现过拟合或欠拟合的情况。如果val_loss函数的数值一直在下降,说明模型在训练过程中在验证集上的表现一直在改善。如果val_loss函数的数值开始上升,说明模型可能已经开始过拟合了,需要调整模型的复杂度或者调整其他超参数。 总之,val_loss函数是用于评估模型在验证集上的损失函数,通过计算模型预测结果与验证集标签之间的差异来评估模型在验证集上的性能。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旺旺棒棒冰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值