【问题标题】:Validation loss for pytorch Faster-RCNNpytorch Faster-RCNN 的验证损失
【发布时间】:2023-04-09 16:38:01
【问题描述】:

我目前正在使用从 pytorch 预训练的 Faster-RCNN 模型(例如在 torchvision tutorial 中)的迁移学习对自定义数据集进行对象检测。 我想在每个时期结束时计算验证损失字典(如在训练模式下)。 我可以像这样在训练模式下运行模型进行验证:

model.train()
for images, targets in data_loader_val:
    images = [image.to(device) for image in images]
    targets = [{k: v.to(device) for k, v in t.items()} for t in targets]

    with torch.no_grad():
         val_loss_dict = model(images, targets)
         print(val_loss_dict)

但我不认为这是“正确”的验证方式(导致一些特殊层,如 dropout 和 batch norm 在 eval/train 模式下的工作方式不同)。并且在 eval 模式下,模型返回预测的 bbox(如预期的那样)。我可以为此使用一些内置函数吗?

谢谢。

【问题讨论】:

  • 很抱歉,我似乎不太明白这个问题,但有什么反对model.eval()
  • @marhoruf 调用 model.eval() 禁用 dropout 并更改批处理规范以使用历史统计,在验证之前调用它。同样model.train() 应该在训练之前被调用。默认情况下,模块处于训练模式。
  • 这是一个有效的问题。虽然始终计算损失和输出,但目前 torchvision 在训练模式下返回损失 onyl,请参阅此行:github.com/pytorch/vision/blob/…

标签: python machine-learning computer-vision pytorch object-detection


【解决方案1】:

有一些关于这个问题的讨论here。结论是在训练模式下计算验证损失是绝对有效的。 val loss的数值本身没有意义,只有趋势重要,防止过拟合。因此,虽然训练模式确实改变了损失的数值,但它仍然可以使用。


然而,这里还有另一个效率问题,以防您在验证过程中还需要模型输出(通常用于计算 IoU、准确性等)。现在,torchvision 中的 RCNN 会根据训练/评估模式为您提供损失或输出。

更新: 不幸的是,我意识到此修复程序不起作用。必须修补所有子模块以计算损失和输出。太糟糕了。

我的肮脏解决方案是修补 GeneralizedRCNN 类,其中 FasterRCNN 继承。问题出在 this 行,在eager_outputs()。解决方法:

    return losses, detections

model = fasterrcnn_resnet50_fpn() model.eager_outputs =
eager_outputs_patch

现在您可以在单次推理运行后获得两个输出:model.train() with torch.no_grad(): loss_dict, outputs = model(images, targets). # yaay, now we have both! 请注意,您仍然需要将模型置于训练模式 为了也有损失。在评估模式GeneralizedRCNN's 子模块(rpn,roi_heads)不计算任何损失,loss_dict 是空的。

【讨论】:

    【解决方案2】:

    我通过编辑Generalized RCNN、RPN、roi_heads解决了这个问题。只需添加一个 if 语句来处理传递目标时即使不在训练模式下仍会计算损失。例如在 RPN 中:

    losses = {}
        if self.training:
            assert targets is not None
            labels, matched_gt_boxes = self.assign_targets_to_anchors(anchors, targets)
            regression_targets = self.box_coder.encode(matched_gt_boxes, anchors)
            loss_objectness, loss_rpn_box_reg = self.compute_loss(
                objectness, pred_bbox_deltas, labels, regression_targets)
            losses = {
                "loss_objectness": loss_objectness,
                "loss_rpn_box_reg": loss_rpn_box_reg,
            }
        else:
            if targets is not None:
                labels, matched_gt_boxes = self.assign_targets_to_anchors(anchors, targets)
                regression_targets = self.box_coder.encode(matched_gt_boxes, anchors)
                loss_objectness, loss_rpn_box_reg = self.compute_loss(
                    objectness, pred_bbox_deltas, labels, regression_targets)
                losses = {
                    "loss_objectness": loss_objectness,
                    "loss_rpn_box_reg": loss_rpn_box_reg,
                }
    

    【讨论】:

      猜你喜欢
      • 2021-03-03
      • 2021-11-02
      • 2020-12-24
      • 2018-06-14
      • 2020-06-17
      • 2016-09-26
      • 1970-01-01
      • 2022-01-21
      相关资源
      最近更新 更多