损失函数总结(九):SoftMarginLoss、MultiLabelSoftMarginLoss
- 1 引言
- 2 损失函数
- 2.1 SoftMarginLoss
- 2.2 MultiLabelSoftMarginLoss
- 3 总结
1 引言
在前面的文章中已经介绍了介绍了一系列损失函数 (L1Loss
、MSELoss
、BCELoss
、CrossEntropyLoss
、NLLLoss
、CTCLoss
、PoissonNLLLoss
、GaussianNLLLoss
、KLDivLoss
、BCEWithLogitsLoss
、MarginRankingLoss
、HingeEmbeddingLoss
、MultiMarginLoss
、MultiLabelMarginLoss
)。在这篇文章中,会接着上文提到的众多损失函数继续进行介绍,给大家带来更多不常见的损失函数的介绍。这里放一张损失函数的机理图:
2 损失函数
2.1 SoftMarginLoss
SoftMarginLoss 用来优化二分类的逻辑损失
。计算给定一个输入x(二维张量)和对应的标签y(一维张量,取值为-1或1)之间的损失值。SoftMarginLoss 的数学表达式如下:
l
o
s
s
(
x
,
y
)
=
∑
i
l
o
g
(
1
+
e
x
p
(
−
y
[
i
]
∗
x
[
i
]
)
)
x
.
n
e
l
e
m
e
n
t
(
)
loss(x,y)= \sum_i\frac{log(1+exp(−y[i]∗x[i]))}{x.nelement()}
loss(x,y)=i∑x.nelement()log(1+exp(−y[i]∗x[i]))
其中, x . n e l e m e n t ( ) x.nelement() x.nelement() 表示元素 x x x 的元素个数。
代码实现(Pytorch):
inputs = torch.tensor([[0.3, 0.7], [0.5, 0.5]])
target = torch.tensor([[-1, 1], [1, -1]], dtype=torch.float)
loss_f = nn.SoftMarginLoss(reduction='none')
loss = loss_f(inputs, target)
print("SoftMargin: ", loss)
结果是:
SoftMargin: tensor([[0.8544, 0.4032],
[0.4741, 0.9741]])
关于该激活函数,在siamese net或者Triplet net任务中被广泛使用。。。。
2.2 MultiLabelSoftMarginLoss
MultiLabelSoftMarginLoss 是 SoftmarginLoss 损失函数的多标签版本
。MultiLabelSoftMarginLoss 基于输入x
(二维张量)和目标y
(二维张量)的最大交叉熵
,优化多标签分类(one-versus-al)的损失。MultiLabelSoftMarginLoss 的数学表达式如下:
l
o
s
s
(
x
,
y
)
=
−
1
C
∗
∑
i
y
[
i
]
∗
l
o
g
(
(
1
+
e
x
p
(
−
x
[
i
]
)
)
−
1
)
+
(
1
−
y
[
i
]
)
∗
log
e
x
p
(
−
x
[
i
]
)
1
+
e
x
p
(
−
x
[
i
]
)
loss(x, y) = -\frac{1}{C}*\sum_iy[i]*log((1+exp(-x[i]))^{-1}) + (1-y[i]) * \log \frac{exp(-x[i])}{1+exp(-x[i])}
loss(x,y)=−C1∗i∑y[i]∗log((1+exp(−x[i]))−1)+(1−y[i])∗log1+exp(−x[i])exp(−x[i])
代码实现(Pytorch):
import torch
import torch.nn.functional as F
import torch.nn as nn
import math
def validate_loss(output, target, weight=None, pos_weight=None):
output = F.sigmoid(output)
# 处理正负样本不均衡问题
if pos_weight is None:
label_size = output.size()[1]
pos_weight = torch.ones(label_size)
# 处理多标签不平衡问题
if weight is None:
label_size = output.size()[1]
weight = torch.ones(label_size)
val = 0
for li_x, li_y in zip(output, target):
for i, xy in enumerate(zip(li_x, li_y)):
x, y = xy
loss_val = pos_weight[i] * y * math.log(x, math.e) + (1 - y) * math.log(1 - x, math.e)
val += weight[i] * loss_val
return -val / (output.size()[0] * output.size(1))
weight = torch.Tensor([0.8, 1, 0.8])
loss = nn.MultiLabelSoftMarginLoss(weight=weight)
x = torch.Tensor([[0.8, 0.9, 0.3], [0.8, 0.9, 0.3], [0.8, 0.9, 0.3], [0.8, 0.9, 0.3]])
y = torch.Tensor([[1, 1, 0], [1, 1, 0], [1, 1, 0], [1, 1, 0]])
print(x.size())
print(y.size())
loss_val = loss(x, y)
print(loss_val.item())
validate_loss = validate_loss(x, y, weight=weight)
print(validate_loss.item())
loss = torch.nn.BCEWithLogitsLoss(weight=weight)
loss_val = loss(x, y)
print(loss_val.item())
代码输出结果:
torch.Size([4, 3])
torch.Size([4, 3])
0.4405062198638916
0.4405062198638916
0.440506249666214
关于该激活函数,在siamese net或者Triplet net任务中被广泛使用。。。。
3 总结
到此,使用 损失函数总结(九) 已经介绍完毕了!!! 如果有什么疑问欢迎在评论区提出,对于共性问题可能会后续添加到文章介绍中。如果存在没有提及的损失函数
也可以在评论区提出,后续会对其进行添加!!!!
如果觉得这篇文章对你有用,记得点赞、收藏并分享给你的小伙伴们哦😄。