美文网首页
loss函数之MultiMarginLoss, MultiLab

loss函数之MultiMarginLoss, MultiLab

作者: ltochange | 来源:发表于2021-06-21 22:36 被阅读0次

    MultiMarginLoss

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

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

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

    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}}

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

    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}}

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

    (1) 当 {margin}-x_{n}[y_{n}]+x_{n}[i]<0时,即 {margin}+x_{n}[i]<x_{n}[y_{n}], 该样本被误认为类别iloss为0。

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

    (2)当 {margin}-x_{n}[y_{n}]+x_{n}[i]>0时,该样本被误认为类别iloss{margin}-x_{n}[y_{n}]+x_{n}[i], 分为两种情况:

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

    • {margin}+x_{n}[i]>x_{n}[i]>x_{n}[y_{n}],对应非常难分类样本,容易被分为类别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即是wsize_averagereduce已经弃用。reduction有三种取值mean, sum, none,对应不同的返回\ell(x, y). 默认为mean,对应于一般情况下整体loss的计算。

    L=\left\{l_{1}, \ldots, l_{N}\right\}
    \ell(x, y)=\left\{\begin{array}{ll}\operatorname L, & \text { ifreduction }=\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.

    p 值默认为1,另外可设为2,其他数值不支持。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

    对于包含N个样本的batch数据 D(x, y)x为神经网络的输出,y是真实的类别标签。

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

    l_{n}=\frac1{C}{ \sum_{j \in y_{n}}\sum_{i \notin y_{n}} \max (0, 1-x_{n}[j]+x_{n}[i])}

    其中,每个样本对应的标签数量不同,只考虑y_{n}中数值-1之前的连续标签。 若某个样本对应的y_{n}=[2,3,-1,0],表示总的标签有四个,而2和3标签属于该样本,0和1标签不属于该样本。y_{n}=[2,3,-1,0]y_{n}=[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即是wsize_averagereduce已经弃用。reduction有三种取值mean, sum, none,对应不同的返回\ell(x, y). 默认为mean,对应于一般情况下整体loss的计算。

    L=\left\{l_{1}, \ldots, l_{N}\right\}
    \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.

    例子:

    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函数之MultiMarginLoss, MultiLab

          本文链接:https://www.haomeiwen.com/subject/javuyltx.html