损失函数汇总
- 1 目标检测类
- 1.1 分类
- 1.1.1 centerloss
- 1.1.2 arcsoftmax
- 1.1.3 focalloss
- 1.2 人脸
- 1.2.1GIOU_loss
- 1.2.2 DIOU_LOSS
- 1.2.3 CIOU_LOSS
- 1.2.4 IOU_LOSS
- 2 图像分割类
-
1 目标检测类
1.1 分类
1.1.1 centerloss
class Centerloss(nn.Module):
def __init__(self, lambdas, feature_num=2, class_num=10):
super().__init__()
self.lambdas = lambdas
self.center = nn.Parameter(torch.randn(class_num, feature_num), requires_grad=True)
def forward(self, feature, label):
'''每个lable对应的中心点列成一个新的矩阵'''
feature=nn.functional.normalize(feature)
center_exp = self.center.index_select(dim=0, index=label.long())
count = torch.histc(label, bins=int(max(label).item() + 1), min=0, max=int(max(label).item()))
'''每个lable对应种类的个数形成的一个新的一维向量'''
count_exp = count.index_select(dim=0, index=label.long())
loss = self.lambdas / 2 * torch.mean(torch.div(torch.sum(torch.pow(feature - center_exp, 2), dim=1), count_exp))
return loss
1.1.2 arcsoftmax
class ArcNet(nn.Module):
def __init__(self,feature_dim=2,cls_dim=10):
super().__init__()
self.W=nn.Parameter(torch.randn(feature_dim,cls_dim).cuda(),requires_grad=True)
def forward(self, feature,m=1,s=10):
x = F.normalize(feature,dim=1)
w = F.normalize(self.W, dim=0)
s = torch.sqrt(torch.sum(torch.pow(x, 2))) * torch.sqrt(torch.sum(torch.pow(w, 2)))
cosa = torch.matmul(x, w)/s
"标准化后的x(-1,1)再求平方(1,1),相当于求它的单位向量(1),所以求x的平方和就是批次100*1=100"
"同理标准化后的w有10个维度,就等于10*1=10"
"所以s就等于sqrt(100)*sqrt(10)≈31.6"
a=torch.acos(cosa)
arcsoftmax = torch.exp(
s * torch.cos(a + m)) / (torch.sum(torch.exp(s * cosa), dim=1, keepdim=True) - torch.exp(
s * cosa) + torch.exp(s * torch.cos(a + m)))
return arcsoftmax
1.1.3 focalloss
from torch import nn
import torch
from torch.nn import functional as F
class focal_loss(nn.Module):
def __init__(self, alpha=0.25, gamma=2, num_classes=2, size_average=True):
"""
focal_loss损失函数, -α(1-yi)**γ *ce_loss(xi,yi)
步骤详细的实现了 focal_loss损失函数.
:param alpha: 阿尔法α,类别权重. 当α是列表时,为各类别权重,当α为常数时,类别权重为[α, 1-α, 1-α, ....],常用于 目标检测算法中抑制背景类 , retainnet中设置为0.25
:param gamma: 伽马γ,难易样本调节参数. retainnet中设置为2
:param num_classes: 类别数量
:param size_average: 损失计算方式,默认取均值
"""
super(focal_loss, self).__init__()
self.size_average = size_average
if isinstance(alpha, list):
assert len(alpha) == num_classes
self.alpha = torch.Tensor(alpha)
else:
assert alpha < 1
self.alpha = torch.zeros(num_classes)
self.alpha[0] += alpha
self.alpha[1:] += (1 - alpha)
self.gamma = gamma
def forward(self, preds, labels):
"""
focal_loss损失计算
:param preds: float32 cpu 预测类别. size:[B,N,C] or [B,C] 分别对应与检测与分类任务, B 批次, N检测框数, C类别数
:param labels: int64 cpu 实际类别. size:[B,N] or [B]
:return:
"""
preds = preds.view(-1, preds.size(-1))
self.alpha = self.alpha.to(preds.device)
preds_logsoft = F.log_softmax(preds, dim=1)
preds_softmax = torch.exp(preds_logsoft)
preds_softmax = preds_softmax.gather(1, labels.reshape(-1, 1))
preds_logsoft = preds_logsoft.gather(1, labels.reshape(-1, 1))
self.alpha = self.alpha.gather(0, labels.view(-1))
loss = -torch.mul(torch.pow((1 - preds_softmax), self.gamma),
preds_logsoft)
loss = torch.mul(self.alpha, loss.t())
if self.size_average:
loss = loss.mean()
else:
loss = loss.sum()
return loss
1.2 人脸
1.2.1GIOU_loss
1、解决具有相同重叠面积,损失相同的问题
2、解决不相交的情况,损失都为0
def Giou(rec1,rec2):
x1,x2,y1,y2 = rec1
x3,x4,y3,y4 = rec2
iou = Iou(rec1,rec2)
area_C = (max(x1,x2,x3,x4)-min(x1,x2,x3,x4))*(max(y1,y2,y3,y4)-min(y1,y2,y3,y4))
area_1 = (x2-x1)*(y1-y2)
area_2 = (x4-x3)*(y3-y4)
sum_area = area_1 + area_2
w1 = x2 - x1
w2 = x4 - x3
h1 = y1 - y2
h2 = y3 - y4
W = min(x1,x2,x3,x4)+w1+w2-max(x1,x2,x3,x4)
H = min(y1,y2,y3,y4)+h1+h2-max(y1,y2,y3,y4)
Area = W*H
add_area = sum_area - Area
end_area = (area_C - add_area)/area_C
giou = iou - end_area
return giou
1.2.2 DIOU_LOSS
def Diou(bboxes1, bboxes2):
rows = bboxes1.shape[0]
cols = bboxes2.shape[0]
dious = torch.zeros((rows, cols))
if rows * cols == 0:
return dious
exchange = False
if bboxes1.shape[0] > bboxes2.shape[0]:
bboxes1, bboxes2 = bboxes2, bboxes1
dious = torch.zeros((cols, rows))
exchange = True
w1 = bboxes1[:, 2] - bboxes1[:, 0]
h1 = bboxes1[:, 3] - bboxes1[:, 1]
w2 = bboxes2[:, 2] - bboxes2[:, 0]
h2 = bboxes2[:, 3] - bboxes2[:, 1]
area1 = w1 * h1
area2 = w2 * h2
center_x1 = (bboxes1[:, 2] + bboxes1[:, 0]) / 2
center_y1 = (bboxes1[:, 3] + bboxes1[:, 1]) / 2
center_x2 = (bboxes2[:, 2] + bboxes2[:, 0]) / 2
center_y2 = (bboxes2[:, 3] + bboxes2[:, 1]) / 2
inter_max_xy = torch.min(bboxes1[:, 2:],bboxes2[:, 2:])
inter_min_xy = torch.max(bboxes1[:, :2],bboxes2[:, :2])
out_max_xy = torch.max(bboxes1[:, 2:],bboxes2[:, 2:])
out_min_xy = torch.min(bboxes1[:, :2],bboxes2[:, :2])
inter = torch.clamp((inter_max_xy - inter_min_xy), min=0)
inter_area = inter[:, 0] * inter[:, 1]
inter_diag = (center_x2 - center_x1)**2 + (center_y2 - center_y1)**2
outer = torch.clamp((out_max_xy - out_min_xy), min=0)
outer_diag = (outer[:, 0] ** 2) + (outer[:, 1] ** 2)
union = area1+area2-inter_area
dious = inter_area / union - (inter_diag) / outer_diag
dious = torch.clamp(dious,min=-1.0,max = 1.0)
if exchange:
dious = dious.T
return dious
1.2.3 CIOU_LOSS
def Ciou(bboxes1, bboxes2):
rows = bboxes1.shape[0]
cols = bboxes2.shape[0]
cious = torch.zeros((rows, cols))
if rows * cols == 0:
return cious
exchange = False
if bboxes1.shape[0] > bboxes2.shape[0]:
bboxes1, bboxes2 = bboxes2, bboxes1
cious = torch.zeros((cols, rows))
exchange = True
w1 = bboxes1[:, 2] - bboxes1[:, 0]
h1 = bboxes1[:, 3] - bboxes1[:, 1]
w2 = bboxes2[:, 2] - bboxes2[:, 0]
h2 = bboxes2[:, 3] - bboxes2[:, 1]
area1 = w1 * h1
area2 = w2 * h2
center_x1 = (bboxes1[:, 2] + bboxes1[:, 0]) / 2
center_y1 = (bboxes1[:, 3] + bboxes1[:, 1]) / 2
center_x2 = (bboxes2[:, 2] + bboxes2[:, 0]) / 2
center_y2 = (bboxes2[:, 3] + bboxes2[:, 1]) / 2
inter_max_xy = torch.min(bboxes1[:, 2:],bboxes2[:, 2:])
inter_min_xy = torch.max(bboxes1[:, :2],bboxes2[:, :2])
out_max_xy = torch.max(bboxes1[:, 2:],bboxes2[:, 2:])
out_min_xy = torch.min(bboxes1[:, :2],bboxes2[:, :2])
inter = torch.clamp((inter_max_xy - inter_min_xy), min=0)
inter_area = inter[:, 0] * inter[:, 1]
inter_diag = (center_x2 - center_x1)**2 + (center_y2 - center_y1)**2
outer = torch.clamp((out_max_xy - out_min_xy), min=0)
outer_diag = (outer[:, 0] ** 2) + (outer[:, 1] ** 2)
union = area1+area2-inter_area
u = (inter_diag) / outer_diag
iou = inter_area / union
with torch.no_grad():
arctan = torch.atan(w2 / h2) - torch.atan(w1 / h1)
v = (4 / (math.pi ** 2)) * torch.pow((torch.atan(w2 / h2) - torch.atan(w1 / h1)), 2)
S = 1 - iou
alpha = v / (S + v)
w_temp = 2 * w1
ar = (8 / (math.pi ** 2)) * arctan * ((w1 - w_temp) * h1)
cious = iou - (u + alpha * ar)
cious = torch.clamp(cious,min=-1.0,max = 1.0)
if exchange:
cious = cious.T
return cious
1.2.4 IOU_LOSS
import numpy as np
def Iou(box1, box2, wh=False):
if wh == False:
xmin1, ymin1, xmax1, ymax1 = box1
xmin2, ymin2, xmax2, ymax2 = box2
else:
xmin1, ymin1 = int(box1[0]-box1[2]/2.0), int(box1[1]-box1[3]/2.0)
xmax1, ymax1 = int(box1[0]+box1[2]/2.0), int(box1[1]+box1[3]/2.0)
xmin2, ymin2 = int(box2[0]-box2[2]/2.0), int(box2[1]-box2[3]/2.0)
xmax2, ymax2 = int(box2[0]+box2[2]/2.0), int(box2[1]+box2[3]/2.0)
xx1 = np.max([xmin1, xmin2])
yy1 = np.max([ymin1, ymin2])
xx2 = np.min([xmax1, xmax2])
yy2 = np.min([ymax1, ymax2])
area1 = (xmax1-xmin1) * (ymax1-ymin1)
area2 = (xmax2-xmin2) * (ymax2-ymin2)
inter_area = (np.max([0, xx2-xx1])) * (np.max([0, yy2-yy1]))
iou = inter_area / (area1+area2-inter_area+1e-6)
return iou
2 图像分割类
2.1 Dice loss
class SoftDiceLoss(nn.Module):
def __init__(self, weight=None, size_average=True, sigmoid=False):
super(SoftDiceLoss, self).__init__()
self.sigmoid = sigmoid
def forward(self, logits, targets):
num = targets.size(0)
smooth = 1
if self.sigmoid == True:
logits = torch.sigmoid(logits)
m1 = logits.view(num, -1)
m2 = targets.view(num, -1)
intersection = (m1 * m2)
dice = 2. * (intersection.sum() + smooth) / ((m1 ** 2).sum() + (m2 ** 2).sum() + smooth)
loss = 1 - dice.mean()
return loss
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)