MultiMarginLoss
多分类合页损失函数(hinge loss),对于一个样本不是考虑样本输出与真实类别之间的误差,而是考虑对应真实类别与其他类别之间的误差
对于包含个样本的batch数据 ,为神经网络的输出,是真实的类别标签,假设类别数为, 。
第个样本的损失值计算如下:
为了处理多个类别之间的样本不平衡问题,对于每一类可传入相应的权值。
若, 由以上公式可知:
(1) 当 时,即 , 该样本被误认为类别的为0。
此时,样本预测为正确类别的概率大于预测为类别的概率,并且差值大于。 这样的样本被认为是易分类样本,直接忽略其带来的误差。
(2)当 时,该样本被误认为类别的为, 分为两种情况:
-
,对应难分类样本,样本被误认为类别的概率值小于正确类别,但是两者的差值小于。
-
,对应非常难分类样本,容易被分为类别
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
即是。size_average
与reduce
已经弃用。reduction有三种取值mean
, sum
, none
,对应不同的返回. 默认为mean
,对应于一般情况下整体的计算。
值默认为1,另外可设为2,其他数值不支持。也是认为设定的值,默认为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
应用于一个样本对应多个真实标签的情况,但是标签总数不超过
对于包含个样本的batch数据 ,为神经网络的输出,是真实的类别标签。
第个样本的损失值计算如下:
其中,每个样本对应的标签数量不同,只考虑中数值之前的连续标签。 若某个样本对应的,表示总的标签有四个,而2和3标签属于该样本,0和1标签不属于该样本。 与两种表示相同。
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
即是。size_average
与reduce
已经弃用。reduction有三种取值mean
, sum
, none
,对应不同的返回. 默认为mean
,对应于一般情况下整体的计算。
例子:
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吗? 这里不是很奇怪嘛。
网友评论