百度Apollo车道线分割比赛三(训练网络)
百度Apollo车道线分割比赛一(数据处理)
百度Apollo车道线分割比赛二(模型搭建)
前面已经搭建好了2个分割模型,数据也处理好了,接下来该训练网络了,训练网络前我们需要有个网络训练的衡量标准metric ,本实现以mIOU作为衡量的标准。另外我们采用ce_loss 和 dice_loss去解决背景 dice loss for postive,bce loss for negtive ,dice loss可以很好的优化模型的dice score,而bce loss训练出来的分类器可以很好地找出negtive sample。
一. metrics.代码如下:
def compute_iou(pred, gt, result):
"""
pred : [N, H, W]
gt: [N, H, W]
"""
pred = pred.cpu().numpy()
gt = gt.cpu().numpy()
for i in range(8):
single_gt=gt==i
single_pred=pred==i
temp_tp = np.sum(single_gt * single_pred)
temp_ta = np.sum(single_pred) + np.sum(single_gt) - temp_tp
result["TP"][i] += temp_tp
result["TA"][i] += temp_ta
return result #计算iou
二,loss,dice_loss ,bc_loss ,focal_loss 代码如下:注意计算loss时根据需要将label转为one_hot编码:
#bce_loss
class MySoftmaxCrossEntropyLoss(nn.Module):
def __init__(self, nbclasses):
super(MySoftmaxCrossEntropyLoss, self).__init__()
self.nbclasses = nbclasses
def forward(self, inputs, target):
if inputs.dim() > 2:
inputs = inputs.view(inputs.size(0), inputs.size(1), -1) # N,C,H,W => N,C,H*W
inputs = inputs.transpose(1, 2) # N,C,H*W => N,H*W,C
inputs = inputs.contiguous().view(-1, self.nbclasses) # N,H*W,C => N*H*W,C
target = target.view(-1)
return nn.CrossEntropyLoss(reduction="mean")(inputs, target)
#dice_loss
class BinaryDiceLoss(nn.Module):
"""Dice loss of binary class
Args:
smooth: A float number to smooth loss, and avoid NaN error, default: 1
p: Denominator value: \sum{x^p} + \sum{y^p}, default: 2
predict: A tensor of shape [N, *]
target: A tensor of shape same with predict
reduction: Reduction method to apply, return mean over batch if 'mean',
return sum if 'sum', return a tensor of shape [N,] if 'none'
Returns:
Loss tensor according to arg reduction
Raise:
Exception if unexpected reduction
"""
def __init__(self, smooth=1, p=2, reduction='mean'):
super(BinaryDiceLoss, self).__init__()
self.smooth = smooth
self.p = p
self.reduction = reduction
def forward(self, predict, target):
assert predict.shape[0] == target.shape[0], "predict & target batch size don't match"
predict = predict.contiguous().view(predict.shape[0], -1)
target = target.contiguous().view(target.shape[0], -1)
num = 2*torch.sum(torch.mul(predict, target), dim=1) + self.smooth
den = torch.sum(predict.pow(self.p) + target.pow(self.p), dim=1) + self.smooth
loss = 1 - num / den
if self.reduction == 'mean':
return loss.mean()
elif self.reduction == 'sum':
return loss.sum()
elif self.reduction == 'none':
return loss
else:
raise Exception('Unexpected reduction {}'.format(self.reduction))
class DiceLoss(nn.Module):
"""Dice loss, need one hot encode input
Args:
weight: An array of shape [num_classes,]
ignore_index: class index to ignore
predict: A tensor of shape [N, C, *]
target: A tensor of same shape with predict
other args pass to BinaryDiceLoss
Return:
same as BinaryDiceLoss
"""
def __init__(self, weight=None, ignore_index=None, **kwargs):
super(DiceLoss, self).__init__()
self.kwargs = kwargs
self.weight = weight
self.ignore_index = ignore_index
def forward(self, predict, target):
assert predict.shape == target.shape, 'predict & target shape do not match'
dice = BinaryDiceLoss(**self.kwargs)
total_loss = 0
predict = F