详解CenterFusion损失函数初始化及前向传播过程

news2024/9/24 10:46:32

CenterFusion损失函数Loss初始化_get_losses函数以及计算过程forward函数

  • 1. 损失函数初始化前序运行逻辑
  • 2. 损失函数初始化
    • 2.1 loss函数初始化——Trainer类中的_get_losses()函数
    • 2.2 model_with_loss的初始化
  • 3. loss计算过程前序运行逻辑
  • 4. loss计算过程
    • 4.1 loss计算函数调用关系
    • 4.2 loss函数实际计算函数——GenericLoss类中的forward()函数
      • 4.2.1 归一化_sigmoid_output()函数
      • 4.2.2 FastFocalLoss
      • 4.2.3 DepthLoss
      • 4.2.4 RegWeightedL1Loss
      • 4.2.5 未执行部分
      • 4.2.6 BinRotLoss
      • 4.2.7 WeightedBCELoss
      • 4.2.8 DepthLoss Ⅱ
      • 4.2.9 BinRotLoss Ⅱ
      • 4.2.10 计算总损失
    • 4.3 loss计算函数传出函数调用关系

1. 损失函数初始化前序运行逻辑

在CenterFusion/src/main.py的main()函数中的51行,调用了Trainer这个class

trainer = Trainer(opt, model, optimizer)

此时调用了Trainer的__init__()函数该函数的定义在CenterFusion/src/lib/trainer.py的130行

def __init__(
  self, opt, model, optimizer=None):
  self.opt = opt
  self.optimizer = optimizer
  self.loss_stats, self.loss = self._get_losses(opt) #loss函数初始化
  self.model_with_loss = ModelWithLoss(model, self.loss, opt) #model_with_loss初始化

2. 损失函数初始化

2.1 loss函数初始化——Trainer类中的_get_losses()函数

首先介绍损失函数的初始化部分_get_losses()函数,该函数的定义在CenterFusion/src/lib/trainer.py的238行
注:_get_losses()函数的调用在CenterFusion/src/lib/trainer.py 134行

  def _get_losses(self, opt):
    loss_order = ['hm', 'wh', 'reg', 'ltrb', 'hps', 'hm_hp', \
      'hp_offset', 'dep', 'dep_sec', 'dim', 'rot', 'rot_sec',
      'amodel_offset', 'ltrb_amodal', 'tracking', 'nuscenes_att', 'velocity']
    # 首先定义最后模型需要回归的头,之后根据这里的头来调用相应的损失函数进行回归
    loss_states = ['tot'] + [k for k in loss_order if k in opt.heads]
    # 计算后loss_states为['tot', 'hm', 'wh', 'reg', 'dep', 'dep_sec', 'dim', 'rot', 'rot_sec', 'amodel_offset', 'nuscenes_att', 'velocity']
    loss = GenericLoss(opt) #这里是损失函数的调用,都封装在了GenericLoss类中
    return loss_states, loss

损失函数类GenericLoss()的定义在CenterFusion/src/lib/trainer.py23行,其中调用了Module父类的构造函数,位置在anaconda3/envs/pytorch17/lib/python3.7/site-packages/torch/nn/modules/module.py的223行

class GenericLoss(torch.nn.Module):
  def __init__(self, opt):
    super(GenericLoss, self).__init__()       #调用Module父类的构造函数对GenericLoss初始化
    self.crit = FastFocalLoss(opt=opt)        #FocalLoss用于之后的分类损失

这里只放了FastFocalLoss类的初始化部分,FastFocalLoss类定义位于CenterFusion/src/lib/model/losses.py的72行,之后在介绍函数具体运算的时候会放上所有的forward函数以及对应需要调用的函数,在该部分对于之后要用到的类也是主要介绍init函数。

class FastFocalLoss(nn.Module):
  '''
  Reimplemented focal loss, exactly the same as the CornerNet version.
  Faster and costs much less memory.
  重新实现了原版centernet的focal loss,与CornerNet版本完全相同,速度更快且需要的内存较少
  '''
  def __init__(self, opt=None):
    super(FastFocalLoss, self).__init__()  #调用Module父类的构造函数对FastFocalLoss初始化
    self.only_neg_loss = _only_neg_loss   #这里调用了负样本的损失函数 

论文中对于负样本的损失为
( 1 − Y x y c ) β ( Y ^ x y c ) α log ⁡ ( 1 − Y ^ x y c ) \left(1-Y_{x y c}\right)^{\beta}\left(\widehat{Y}_{x y c}\right)^{\alpha} \log \left(1-\widehat{Y}_{x y c}\right) (1Yxyc)β(Y xyc)αlog(1Y xyc)
其中groundtruth为 Y x y c Y_{xyc} Yxyc
预测的标签为 Y ^ x y c \widehat Y_{xyc} Y xyc
_only_neg_loss()函数就是根据这个公式进行编写的,_only_neg_loss()位于CenterFusion/src/lib/model/losses.py的67行:

def _only_neg_loss(pred, gt):
  gt = torch.pow(1 - gt, 4)
  neg_loss = torch.log(1 - pred) * torch.pow(pred, 2) * gt
  return neg_loss.sum()

下面几个损失可以在debug的时候详细看下,具体都是CenterFusion/src/lib/model/losses.py中的函数调用,与FastFocalLoss类相似,就不一一介绍了,所有损失函数的初始化均调用Module父类的构造函数进行初始化

    self.crit_reg = RegWeightedL1Loss()         #用于计算hm的回归损失
     if 'rot' in opt.heads:
      self.crit_rot = BinRotLoss()              #用于计算alpha观测角的损失
    if 'nuscenes_att' in opt.heads:
      self.crit_nuscenes_att = WeightedBCELoss()#用于计算物体类别的损失
    self.opt = opt
    self.crit_dep = DepthLoss()                 #用于估计深度的损失

在这里插入图片描述

2.2 model_with_loss的初始化

接下来介绍model_with_loss的初始化,该变量初始化使用到了ModelWithLoss类,该class的定义在CenterFusion/src/lib/trainer.py的110行,初始化使用了其__init__()函数,该初始化主要是方便后续前向传播forward()函数的调用
注:ModelWithLoss类的调用在CenterFusion/src/lib/trainer.py 134行

self.model_with_loss = ModelWithLoss(model, self.loss, opt) 
def __init__(self, model, loss, opt):
  super(ModelWithLoss, self).__init__()
  self.opt = opt     #定义传入opt变量
  self.model = model #定义传入model变量
  self.loss = loss   #定义传入loss变量

3. loss计算过程前序运行逻辑

在CenterFusion/src/main.py的main()函数中的84行,调用了Trainer这个class中的train()函数

log_dict_train, _ = trainer.train(epoch, train_loader)

train()函数的定义在CenterFusion/src/lib/trainer.py的405行

def train(self, epoch, data_loader):
  return self.run_epoch('train', epoch, data_loader)  #调用run_epoch()函数

run_epoch()函数的定义在CenterFusion/src/lib/trainer.py的150行,其中开始执行loss计算的函数位于178行

# run one iteration 
output, loss, loss_stats = model_with_loss(batch, phase)

4. loss计算过程

4.1 loss计算函数调用关系

loss计算入口函数为run_epoch()中的model_with_loss()函数,位于CenterFusion/src/lib/trainer.py的178行,其中的loss变量即为得到的loss运算结果

# run one iteration 
output, loss, loss_stats = model_with_loss(batch, phase)

model_with_loss的定义位于CenterFusion/src/lib/trainer.py的151行,定义model_with_loss为self.model_with_loss,该语句位于CenterFusion/src/lib/trainer.py的151行

model_with_loss = self.model_with_loss

而self.model_with_loss则在Trainer类的__init__()函数中初始化为ModelWithLoss类,位于CenterFusion/src/lib/trainer.py的135行

self.model_with_loss = ModelWithLoss(model, self.loss, opt)

故CenterFusion/src/lib/trainer.py的178行的model_with_loss(batch, phase)函数即为调用ModelWithLoss类中的forward()函数,其位置在CenterFusion/src/lib/trainer.py的117行

def forward(self, batch, phase):
  pc_dep = batch.get('pc_dep', None)
  pc_hm = batch.get('pc_hm', None)
  calib = batch['calib'].squeeze(0)

  ## run the first stage
  outputs = self.model(batch['image'], pc_hm=pc_hm, pc_dep=pc_dep, calib=calib)
  
  loss, loss_stats = self.loss(outputs, batch) #计算loss
  return outputs[-1], loss, loss_stats

而计算loss是其中的self.loss()函数,该函数在ModelWithLoss的__init__()函数中进行的定义,其位置在CenterFusion/src/lib/trainer.py的115行

self.loss = loss

等号右边的loss变量为__init__()函数传入的参数,位于CenterFusion/src/lib/trainer.py的111行

class ModelWithLoss(torch.nn.Module):
  def __init__(self, model, loss, opt):  #CenterFusion/src/lib/trainer.py的111行
  super(ModelWithLoss, self).__init__()
  self.opt = opt
  self.model = model
  self.loss = loss

该参数传入在Trainer类的__init__()函数中将self.model_with_loss初始化为ModelWithLoss类时传入,位于CenterFusion/src/lib/trainer.py的135行

self.model_with_loss = ModelWithLoss(model, self.loss, opt)

self.loss为Trainer类中_get_losses()函数的输出结果,位于CenterFusion/src/lib/trainer.py的134行

self.loss_stats, self.loss = self._get_losses(opt)

_get_losses()函数的loss运算及输出位于CenterFusion/src/lib/trainer.py的243,244行,其调用了GenericLoss类

def _get_losses(self, opt):
  loss_order = ['hm', 'wh', 'reg', 'ltrb', 'hps', 'hm_hp', \
    'hp_offset', 'dep', 'dep_sec', 'dim', 'rot', 'rot_sec',
    'amodel_offset', 'ltrb_amodal', 'tracking', 'nuscenes_att', 'velocity']
  loss_states = ['tot'] + [k for k in loss_order if k in opt.heads]
  loss = GenericLoss(opt)    #CenterFusion/src/lib/trainer.py的243行
  return loss_states, loss   #CenterFusion/src/lib/trainer.py的244行

故CenterFusion/src/lib/trainer.py的125行的self.loss()函数实际上调用的是GenericLoss类中的forward()函数

loss, loss_stats = self.loss(outputs, batch)  #CenterFusion/src/lib/trainer.py的125行

4.2 loss函数实际计算函数——GenericLoss类中的forward()函数

4.2.1 归一化_sigmoid_output()函数

GenericLoss类中的forward()函数位于CenterFusion/src/lib/trainer.py的46行

def forward(self, outputs, batch):
  opt = self.opt
  losses = {head: 0 for head in opt.heads}

  for s in range(opt.num_stacks):
    output = outputs[s]
    output = self._sigmoid_output(output) #将输出归一化到0-1之间

_sigmoid_output()位于CenterFusion/src/lib/trainer.py的35行,其主要功能就是将output输入归一化到0~1之间进行输出

def _sigmoid_output(self, output):
  if 'hm' in output:
    output['hm'] = _sigmoid(output['hm'])
  if 'hm_hp' in output:
    output['hm_hp'] = _sigmoid(output['hm_hp'])
  if 'dep' in output:
    output['dep'] = 1. / (output['dep'].sigmoid() + 1e-6) - 1.
  if 'dep_sec' in output and self.opt.sigmoid_dep_sec:
    output['dep_sec'] = 1. / (output['dep_sec'].sigmoid() + 1e-6) - 1.
  return output

其中基本上调用的都是_sigmoid()函数,该函数位于CenterFusion/src/lib/model/utils.py的8行,其中主要是用了torch库中的clamp()函数
torch.clamp()函数是将输入的张量x.sigmoid_()钳制到区间 [min,max],返回值为一个[min,max]之间的新张量

def _sigmoid(x):
  y = torch.clamp(x.sigmoid_(), min=1e-4, max=1-1e-4)
  return y

4.2.2 FastFocalLoss

回到GenericLoss类中的forward()函数,调用了self.crit(),位于CenterFusion/src/lib/trainer.py的55行

    if 'hm' in output:
      losses['hm'] += self.crit(
        output['hm'], batch['hm'], batch['ind'], 
        batch['mask'], batch['cat']) / opt.num_stacks

上述语句中调用了self.crit()函数,而self.crit的初始化使用的FastFocalLoss类,初始化位于CenterFusion/src/lib/trainer.py的26行

self.crit = FastFocalLoss(opt=opt)

故GenericLoss类中的forward()函数中CenterFusion/src/lib/trainer.py的55行的self.crit()函数实际上为调用FastFocalLoss类的forward()函数
FastFocalLoss类的forward()函数位于CenterFusion/src/lib/model/losses.py的81行

class FastFocalLoss(nn.Module):
  '''
  Reimplemented focal loss, exactly the same as the CornerNet version.
  Faster and costs much less memory.
  '''
  def __init__(self, opt=None):
    pass

  def forward(self, out, target, ind, mask, cat):
    '''
    Arguments:
      out, target: B x C x H x W   1*10*112*200
      ind, mask: B x M              
      cat (category id for peaks): B x M
    '''
    neg_loss = self.only_neg_loss(out, target)                       #计算负样本的损失
    pos_pred_pix = _tranpose_and_gather_feat(out, ind) # B x M x C

        def _tranpose_and_gather_feat(feat, ind):  #CenterFusion/src/lib/model/utils.py的22行
          feat = feat.permute(0, 2, 3, 1).contiguous()     #首先将feat从B*C*H*W转换成 BHWC
          feat = feat.view(feat.size(0), -1, feat.size(3)) #之后在变成B*HW*C
          '''
          这里进行维度转换的原因是由于当时在dataset中设置中心点的时候,也是首先将图像展开成向量,之后保存中心点在向量中的位置
          '''
          feat = _gather_feat(feat, ind)
          '''
          _gather_feat函数如下边所示,ind中保存的就是原来2d框中心点在图像中的位置,
          这里由于要使用gather函数获取到预测特征对应位置的值,所以将ind由原来的1*128大小扩展成1*128*10
          加上原来1*128中的第一个值为7458,那么1*128*10中的第一行向量所有的值都为7458,这里是为了取出10类类别中所有的位置
          用于之后的类别二次删选。
          最后得到的特则为1*128*10
          '''
          return feat
        
        def _gather_feat(feat, ind):  ##CenterFusion/src/lib/model/utils.py的16行
          dim = feat.size(2)
          ind = ind.unsqueeze(2).expand(ind.size(0), ind.size(1), dim)
          feat = feat.gather(1, ind)
          return feat

    pos_pred = pos_pred_pix.gather(2, cat.unsqueeze(2)) # B x M    
    '''
    根据每个框的值进行二次删选,加入第一个框也就是上述7458位置对应的类别为第一类,
    那么只是取出了feat中的第一个样本的第一个元素做为预测的概率
    '''
    num_pos = mask.sum()
    pos_loss = torch.log(pos_pred) * torch.pow(1 - pos_pred, 2) * \
               mask.unsqueeze(2)
    #根据focalloss的正样本的公式进行计算损失
    pos_loss = pos_loss.sum() #改图像中对应的所有的bbox的个数
    if num_pos == 0:
      return - neg_loss
    return - (pos_loss + neg_loss) / num_pos #计算平均损失

4.2.3 DepthLoss

回到GenericLoss类中的forward()函数,调用了self.crit_dep(),位于CenterFusion/src/lib/trainer.py的60行

    if 'dep' in output:
      losses['dep'] += self.crit_dep(
        output['dep'], batch['dep'], batch['ind'], 
        batch['dep_mask'], batch['cat']) / opt.num_stacks

上述语句中调用了self.crit_dep()函数,而self.crit_dep的初始化使用的DepthLoss类,初始化位于CenterFusion/src/lib/trainer.py的33行

self.crit_dep = DepthLoss()

故GenericLoss类中的forward()函数中CenterFusion/src/lib/trainer.py的60行的self.crit_dep()函数实际上为调用DepthLoss类的forward()函数
DepthLoss类的forward()函数位于CenterFusion/src/lib/model/losses.py的212行

class DepthLoss(nn.Module):
  def __init__(self, opt=None):
    super(DepthLoss, self).__init__()

  def forward(self, output, target, ind, mask, cat):
    '''
    Arguments:
      out, target: B x C x H x W
      ind, mask: B x M
      cat (category id for peaks): B x M
    '''
    pred = _tranpose_and_gather_feat(output, ind) # B x M x (C) #获取框中心点对应的预测的深度值
    if pred.shape[2] > 1:
      pred = pred.gather(2, cat.unsqueeze(2)) # B x M
    loss = F.l1_loss(pred * mask, target * mask, reduction='sum') #利用torch.nn.functional中的l1损失计算depth的损失值
    loss = loss / (mask.sum() + 1e-4)
    return loss

4.2.4 RegWeightedL1Loss

回到GenericLoss类中的forward()函数,定义了回归头,调用了self.crit_reg(),位于CenterFusion/src/lib/trainer.py的70行

      regression_heads = [
        'reg', 'wh', 'tracking', 'ltrb', 'ltrb_amodal', 'hps', 
        'dim', 'amodel_offset', 'velocity'] #定义回归头

      for head in regression_heads:         #利用回归损失计算其他回归头的损失
        if head in output:
          losses[head] += self.crit_reg(
            output[head], batch[head + '_mask'],
            batch['ind'], batch[head]) / opt.num_stacks

上述语句中调用了self.crit_reg()函数,而self.crit_reg的初始化使用的RegWeightedL1Loss类,初始化位于CenterFusion/src/lib/trainer.py的27行

self.crit_reg = RegWeightedL1Loss()

故GenericLoss类中的forward()函数中CenterFusion/src/lib/trainer.py的70行的self.crit_reg()函数实际上为调用RegWeightedL1Loss类的forward()函数
RegWeightedL1Loss类的forward()函数位于CenterFusion/src/lib/model/losses.py的122行

class RegWeightedL1Loss(nn.Module):
  def __init__(self):
    super(RegWeightedL1Loss, self).__init__()
  
  def forward(self, output, mask, ind, target):
    pred = _tranpose_and_gather_feat(output, ind)
    loss = F.l1_loss(pred * mask, target * mask, reduction='sum') #利用torch.nn.functional中的l1损失计算d回归损失
    loss = loss / (mask.sum() + 1e-4)
    return loss

4.2.5 未执行部分

回到GenericLoss类中的forward()函数,以下两步由于output中没有相关参数使其未执行,位于CenterFusion/src/lib/trainer.py的75行

      if 'hm_hp' in output:                              #没有执行
        losses['hm_hp'] += self.crit(
          output['hm_hp'], batch['hm_hp'], batch['hp_ind'], 
          batch['hm_hp_mask'], batch['joint']) / opt.num_stacks
        if 'hp_offset' in output:                       #没有执行
          losses['hp_offset'] += self.crit_reg(
            output['hp_offset'], batch['hp_offset_mask'],
            batch['hp_ind'], batch['hp_offset']) / opt.num_stacks

4.2.6 BinRotLoss

继续GenericLoss类中的forward()函数,调用了self.crit_rot(),位于CenterFusion/src/lib/trainer.py的84行

      if 'rot' in output:
        losses['rot'] += self.crit_rot(                                    #用于回归alpha观测角
          output['rot'], batch['rot_mask'], batch['ind'], batch['rotbin'],
          batch['rotres']) / opt.num_stacks

上述语句中调用了self.crit_rot()函数,而self.crit_rot的初始化使用的BinRotLoss类,初始化位于CenterFusion/src/lib/trainer.py的29行

if 'rot' in opt.heads:
  self.crit_rot = BinRotLoss()

故GenericLoss类中的forward()函数中CenterFusion/src/lib/trainer.py的84行的self.crit_rot()函数实际上为调用BinRotLoss类的forward()函数
BinRotLoss类的forward()函数位于CenterFusion/src/lib/model/losses.py的149行

class BinRotLoss(nn.Module):
  def __init__(self):
    super(BinRotLoss, self).__init__()
  
  def forward(self, output, mask, ind, rotbin, rotres):
    pred = _tranpose_and_gather_feat(output, ind)          #获取对应位置的alpha观测角相关预测值
    loss = compute_rot_loss(pred, rotbin, rotres, mask)
    return loss

其中,调用了compute_rot_loss()函数,该函数位于CenterFusion/src/lib/model/losses.py的173行

def compute_rot_loss(output, target_bin, target_res, mask):
    # output: (B, 128, 8) [bin1_cls[0], bin1_cls[1], bin1_sin, bin1_cos, 
    #                 bin2_cls[0], bin2_cls[1], bin2_sin, bin2_cos]
    # target_bin: (B, 128, 2) [bin1_cls, bin2_cls]
    # target_res: (B, 128, 2) [bin1_res, bin2_res]
    # mask: (B, 128, 1)
    '''
    这里用于计算alpha观测角的损失,作者在计算该部分的时候将分成区域+对应区域的残差角进行预测
    首先见360°分成两个相交的空间(bin),之后计算预测角度在该区域内的残差角
    如果残差角在相交的区域,那么bin1,bin2对应的值都为1,如果只在一个区域内,则对应位置的值为1,另一个为0
    在预测残差角的时候用的是sin 和cos两个进行预测,
    '''
    output = output.view(-1, 8)
    target_bin = target_bin.view(-1, 2)
    target_res = target_res.view(-1, 2)
    mask = mask.view(-1, 1)
    #前四维的表示bin1的相关预测值,前两个表示在那个bin中,后两个是对应的sin cos值,后四维表示bin2
    #这里是计算bin对应的损失,由于是分类损失用的是交叉熵损失
    loss_bin1 = compute_bin_loss(output[:, 0:2], target_bin[:, 0], mask)        
    loss_bin2 = compute_bin_loss(output[:, 4:6], target_bin[:, 1], mask)
    
    #这里计算残差角的损失
    #如果groundtruth对应bin位置有值的话,则计算对应的sin,cos损失
    loss_res = torch.zeros_like(loss_bin1)
    if target_bin[:, 0].nonzero().shape[0] > 0:
        idx1 = target_bin[:, 0].nonzero()[:, 0]
        valid_output1 = torch.index_select(output, 0, idx1.long())
        valid_target_res1 = torch.index_select(target_res, 0, idx1.long())
        loss_sin1 = compute_res_loss(
          valid_output1[:, 2], torch.sin(valid_target_res1[:, 0]))
        loss_cos1 = compute_res_loss(
          valid_output1[:, 3], torch.cos(valid_target_res1[:, 0]))
        loss_res += loss_sin1 + loss_cos1
    if target_bin[:, 1].nonzero().shape[0] > 0:
        idx2 = target_bin[:, 1].nonzero()[:, 0]
        valid_output2 = torch.index_select(output, 0, idx2.long())
        valid_target_res2 = torch.index_select(target_res, 0, idx2.long())
        loss_sin2 = compute_res_loss(
          valid_output2[:, 6], torch.sin(valid_target_res2[:, 1]))
        loss_cos2 = compute_res_loss(
          valid_output2[:, 7], torch.cos(valid_target_res2[:, 1]))
        loss_res += loss_sin2 + loss_cos2
    return loss_bin1 + loss_bin2 + loss_res

4.2.7 WeightedBCELoss

回到GenericLoss类中的forward()函数,调用了self.crit_nuscenes_att(),位于CenterFusion/src/lib/trainer.py的89行

      if 'nuscenes_att' in output:                            #计算状态损失
        losses['nuscenes_att'] += self.crit_nuscenes_att(
          output['nuscenes_att'], batch['nuscenes_att_mask'],
          batch['ind'], batch['nuscenes_att']) / opt.num_stacks

上述语句中调用了self.crit_nuscenes_att()函数,而self.crit_nuscenes_att的初始化使用的WeightedBCELoss类,初始化位于CenterFusion/src/lib/trainer.py的31行

if 'nuscenes_att' in opt.heads:
  self.crit_nuscenes_att = WeightedBCELoss()

故GenericLoss类中的forward()函数中CenterFusion/src/lib/trainer.py的89行的self.crit_nuscenes_att()函数实际上为调用WeightedBCELoss类的forward()函数
WeightedBCELoss类的forward()函数位于CenterFusion/src/lib/model/losses.py的134行

class WeightedBCELoss(nn.Module):
  def __init__(self):
    super(WeightedBCELoss, self).__init__()
    self.bceloss = torch.nn.BCEWithLogitsLoss(reduction='none')

  def forward(self, output, mask, ind, target):
    # output: B x F x H x W
    # ind: B x M
    # mask: B x M x F
    # target: B x M x F
    pred = _tranpose_and_gather_feat(output, ind) # B x M x F
    loss = mask * self.bceloss(pred, target)  #调用torch.nn.BCEWithLogitsLoss()函数计算
    loss = loss.sum() / (mask.sum() + 1e-4)
    return loss

其中,计算loss时调用了torch.nn.BCEWithLogitsLoss()函数

4.2.8 DepthLoss Ⅱ

回到GenericLoss类中的forward()函数,调用了self.crit_dep(),位于CenterFusion/src/lib/trainer.py的94行

      if 'dep_sec' in output:                                  #计算第二个回归头的深度损失
        losses['dep_sec'] += self.crit_dep(
          output['dep_sec'], batch['dep'], batch['ind'], 
          batch['dep_mask'], batch['cat']) / opt.num_stacks

前序计算中已阐述self.crit_dep()函数,此处不再赘述,详细查看4.2.3

4.2.9 BinRotLoss Ⅱ

回到GenericLoss类中的forward()函数,调用了self.crit_rot(),位于CenterFusion/src/lib/trainer.py的99行

      if 'rot_sec' in output:                                 #计算第二个回归头的角度损失
        losses['rot_sec'] += self.crit_rot(
          output['rot_sec'], batch['rot_mask'], batch['ind'], batch['rotbin'],
          batch['rotres']) / opt.num_stacks

前序计算中已阐述self.crit_dep()函数,此处不再赘述,详细查看4.2.6

4.2.10 计算总损失

回到GenericLoss类中的forward()函数,该函数中将所有的loss求加权和,位于CenterFusion/src/lib/trainer.py的105行

    losses['tot'] = 0
    for head in opt.heads:                                  #计算总的损失
      losses['tot'] += opt.weights[head] * losses[head] 

    return losses['tot'], losses

其中,权值opt.weightsd的定义位于CenterFusion/src/lib/opts.py的510行

    weight_dict = {'hm': opt.hm_weight, 'wh': opt.wh_weight,
                   'reg': opt.off_weight, 'hps': opt.hp_weight,
                   'hm_hp': opt.hm_hp_weight, 'hp_offset': opt.off_weight,
                   'dep': opt.dep_weight, 'dep_res': opt.dep_res_weight,
                   'rot': opt.rot_weight, 'dep_sec': opt.dep_weight,
                   'dim': opt.dim_weight, 'rot_sec': opt.rot_weight,
                   'amodel_offset': opt.amodel_offset_weight,
                   'ltrb': opt.ltrb_weight,
                   'tracking': opt.tracking_weight,
                   'ltrb_amodal': opt.ltrb_amodal_weight,
                   'nuscenes_att': opt.nuscenes_att_weight,
                   'velocity': opt.velocity_weight}
    opt.weights = {head: weight_dict[head] for head in opt.heads}

4.3 loss计算函数传出函数调用关系

GenericLoss类中的forward()函数的返回值中losses[‘tot’]和losses分别对应位于CenterFusion/src/lib/trainer.py的125行ModelWithLoss类的forward()函数中的loss和loss_stats

loss, loss_stats = self.loss(outputs, batch)  #CenterFusion/src/lib/trainer.py的125行

即:loss(ModelWithLoss类的forward())等于losses[‘tot’](GenericLoss类中的forward()返回值),loss_stats(ModelWithLoss类的forward())等于losses(GenericLoss类中的forward()返回值)
ModelWithLoss类的forward()函数的返回值中的loss, loss_stats分别对应位于CenterFusion/src/lib/trainer.py的178行run_epoch()函数中的model_with_loss()函数发返回值loss,loss_stats

# run one iteration 
output, loss, loss_stats = model_with_loss(batch, phase) #CenterFusion/src/lib/trainer.py的178行

之后就是求每一层损失值的平均值作为最终该epoch的loss输出,位于CenterFusion/src/lib/trainer.py的181行调用了pythonstatistics模块的mean()函数

# backpropagate and step optimizer 反向传播和步进优化器
loss = loss.mean()     #求损失值的平均值 CenterFusion/src/lib/trainer.py的181行

至此,loss计算完成,之后便是反向传播

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/611100.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python圆柱体积计算器:简单、高效、快速解决计算难题

Python圆柱体积计算器:简单、高效、快速解决计算难题 圆柱体积是一个在日常生活、工程学、数学等领域都十分普遍的概念,可以用来计算许多实际问题中的体积,比如容器的容量、建筑材料的用量等等。在本文中,我们将介绍如何使用Pyth…

部署和配置DHCP服务器实验:自动分配IP地址和网络配置

部署和配置DHCP服务器实验:自动分配IP地址和网络配置 【实验目的】 部署DHCP服务器。熟悉DHCP服务器的配置方法。验证拓扑。 【实验拓扑】 实验拓扑如图所示。 设备参数如下表所示。 设备 接口 IP地址 子网掩码 默认网关 DHCPSERVE F0/0 172.16.10.1 25…

大学生必知必会技能系列02--虚拟机安装

学习linux的时候,在自己的pc笔记本上安装Linux不太方便,解决方法是,在笔记本上安装 vmware虚拟机,然后再把计划要学习的Linux版本安装到虚拟机中,此时外部电脑能办公,虚拟机上的 代码也能正常运用。 一、VMware 17 虚拟…

2023年6月杭州/广州/东莞/深圳软考(中/高级)认证招生简章

软考是全国计算机技术与软件专业技术资格(水平)考试(简称软考)项目,是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试,既属于国家职业资格考试,又是职称资格考试。 系统集成…

09 【CLI 初始化脚手架 Vue零碎的一些知识】

09 【CLI 初始化脚手架 Vue零碎的一些知识】 1.Vue CLI 初始化脚手架 1.1具体步骤 1如果下载缓慢请配置npm淘宝镜像npm config set registry http://registry.npm.taobao.org 2全局安装 vue/cli npm install -g vue/cli 3切换到创建项目的目录,使用命令创建项目v…

递增子序列

1题目 给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。 示例 1…

苹果MacOS系统傻瓜式本地部署AI绘画Stable Diffusion教程

Stable Diffusion的部署对小白来说非常麻烦,特别是又不懂技术的人。今天分享两个一键傻瓜式安装包,对小白来说非常有用。下面两个任选一个安装就可以。 一、DiffusionBee 简单介绍 DiffusionBee是基于stable diffusion的一个安装包,有图形…

BIO NIO AIO之间的区别与联系

目录 前言五种I/O模型1.同步阻塞I/O, BIO2.同步非阻塞I/O, NIO3.多路复用IO4.信号驱动I/O5.异步I/O,AIO 同步阻塞?异步非阻塞?1.阻塞I/O 与 非阻塞I/O2.同步I/O 与 异步I/O Netty采用了哪种I/O模型? 前言 Unix系统下的五种基本I/O模型 blo…

【Jenkins】什么?前端还能用Jenkins一键部署?

前置要求: Jenkins安装nodejs插件(本篇文章会教) Linux安装Node.js(图文解说详细版) 如果你是一名前端工程师,那么你可能会对Jenkins这个自动化构建工具并不陌生。但是,你有没有想过在前端项目中…

Python+Django图书商城网站前后端

程序示例精选 PythonDjango图书商城网站前后端 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<PythonDjango图书商城网站前后端 >>编写代码&#xff0c;代码整洁&#xff0c;规…

飞行器姿态计算

在飞行器的控制中&#xff0c;姿态计算是至关重要的一步。姿态计算的目标是确定飞行器相对于参考坐标系的姿态&#xff0c;通常以欧拉角&#xff08;滚转、俯仰和偏航&#xff09;或四元数的形式表示。 以下是姿态计算的原理和常用方法的简要介绍&#xff1a; 原理&#xff1a…

数据库系列:数据库高可用及无损扩容

1 背景 在大型互联网场景中&#xff0c;数据库的高可用性显得尤为重要&#xff0c;为了保证稳定性&#xff0c;一般需要采用强化的架构模式&#xff0c;以保证数据层能够提供持续有效的稳定支撑。 2 高可用架构的基本演进过程 2.1 基本的数据库架构 每个服务对应一个存储服…

FinancesOnline 2022/2023 10大IT趋势预测

在过去几十年的时间里&#xff0c;全世界的计算能力达到了万亿倍的增长。太空、军事和工业研究促成了范式的转变。与此同时&#xff0c;新冠肺炎大流行等不可预见的事件迫使人们去迎接新的技术&#xff0c;采用与以往不同的技术路径&#xff0c;这导致了IT趋势越来越难以跟上。…

阿里云轻量服务器--Docker--Rabbitmq安装

1 Rabbitmq 介绍&#xff1a; RabbitMQ 是一个开源的消息代理软件&#xff0c;通常用于构建分布式系统&#xff0c;支持多种消息传递协议&#xff0c;并支持多种编程语言。RabbitMQ 基于 AMQP (Advanced Message Queuing Protocol) 协议开发&#xff0c;是一个高可用、高可靠、…

3.完成ODS层数据采集操作

将原始数据导入mysql 1 选中mysql 运行脚本 2 验证结果 数据存储格式和压缩方案 存储格式 分类 1.行式存储(textFile) 缺点:可读性较好 执行 select * 效率比较高 缺点:耗费磁盘资源 执行 select 字段 效率比较低 2.列式存储(orc) 优点:节省磁盘空间. 执行 select 字段…

配电网可靠性评估(4)—(顶刊复现)基于线性规划的配电网可靠性评估

之前的博客中介绍了配电网可靠性评估的三种方法、分别是解析法中的最小路法&#xff0c;以及序贯蒙特卡罗模拟法及非序贯蒙特卡洛模拟法&#xff0c;顺带提到了含有分布式电源的配电网可靠性评估方法。 配电网可靠性评估&#xff08;一&#xff09;最小路法和非序贯蒙特卡洛模…

Elai.io:AI视频生成平台

【产品介绍】 Elai.io是一个基于人工智能的AI视频生成平台&#xff0c;可以让你只用文本就能制作出有真人主持的专业视频。无论你是想做教育、营销、企业沟通或者其他类型的视频内容&#xff0c;Elai.io都可以帮你节省时间和成本&#xff0c;提高效率和质量。Elai.io的技术结合…

618数码产品攻略,列举几款2023年618必入的数码产品

​一年一度大型促销的618节日转眼间第一波就已经过去了&#xff0c;在这种各类优惠活动接踵而至的日子里&#xff0c;很多人都是准备着更换新东西的时刻&#xff0c;不过也会存在着一部分人&#xff0c;想要入手数码好物&#xff0c;但又不知道该如何去挑选&#xff0c;毕竟现在…

2.2 事件驱动的reactor网络设计模型

在网络io、io多路复用select/poll/epoll、基于事件驱动的reactor中介绍了多种网络I/O方式&#xff0c;特别是事件驱动的reactor。其开发效率比直接使用IO多路复用要高&#xff0c;它一般是单线程的&#xff0c;设计目标是希望一个线程使用CPU的全部资源。 并且&#xff0c;相对…

Rxjava2系列:RXjava2.1.7源码下载

找到github项目地址&#xff1a;https://github.com/ReactiveX/RxJava/ 找到右侧的release&#xff0c;点击打开。 搜索2.1.7 (2.1.7是这篇文章&#xff1a;RxJava 是如何实现线程切换的&#xff08;上&#xff09;的源码版本&#xff09; 找到Assert&#xff0c;下载 解…