WZMIAOMIAO/deep-learning-for-image-processing · error · ValueError

backbone should contain an attribute out_channels specifying

Error message

backbone should contain an attribute out_channels specifying the number of output channels (assumed to be the same for all the levels)

What it means

RetinaNet.__init__ requires the backbone object to expose an integer attribute out_channels, because the FPN and head construction need the number of channels of every pyramid level (assumed uniform). torchvision-style backbones (e.g. resnet50_fpn_backbone) set it; a raw nn.Module without it cannot be wired into the detection heads.

Source

Thrown at pytorch_object_detection/retinaNet/network_files/retinanet.py:304

        'proposal_matcher': det_utils.Matcher,
    }

    def __init__(self, backbone, num_classes,
                 # transform parameters
                 min_size=800, max_size=1333,
                 image_mean=None, image_std=None,
                 # Anchor parameters
                 anchor_generator=None, head=None,
                 proposal_matcher=None,
                 score_thresh=0.05,
                 nms_thresh=0.5,
                 detections_per_img=100,
                 fg_iou_thresh=0.5, bg_iou_thresh=0.4,
                 topk_candidates=1000):
        super(RetinaNet, self).__init__()

        if not hasattr(backbone, "out_channels"):
            raise ValueError(
                "backbone should contain an attribute out_channels "
                "specifying the number of output channels (assumed to be the "
                "same for all the levels)"
            )

        self.backbone = backbone

        assert isinstance(anchor_generator, (AnchorsGenerator, type(None)))

        if anchor_generator is None:
            # 原论文中说在每个预测特征层上除了使用给定的尺度x外,还要额外添加x*2^(1/3)和x*2^(2/3)这两个尺度
            # 五个预测特征层采用的原始尺度分别为32, 64, 128, 256, 512
            # 注意尺度和面积的关系,面积=尺度^2
            anchor_sizes = tuple((x, int(x * 2 ** (1.0 / 3)), int(x * 2 ** (2.0 / 3)))
                                 for x in [32, 64, 128, 256, 512])
            # 对于每个预测特征层上anchors,都会使用三种比例
            aspect_ratios = ((0.5, 1.0, 2.0),) * len(anchor_sizes)
            anchor_generator = AnchorsGenerator(anchor_sizes, aspect_ratios)

View on GitHub (pinned to 1ec3fe6f37)

Solutions

  1. Set self.out_channels = <channels of last FPN level> in your backbone's __init__.
  2. Use the repo's provided builder (e.g. resnet50_fpn_backbone) which sets out_channels automatically.
  3. If wrapping, forward the attribute: wrapper.out_channels = inner_backbone.out_channels.
  4. Verify with hasattr(backbone, 'out_channels') before constructing RetinaNet.

Example fix

// before
class MyBackbone(nn.Module):
    def __init__(self):
        super().__init__()
        self.body = resnet50()
retina = RetinaNet(backbone=MyBackbone(), num_classes=91)
// after
class MyBackbone(nn.Module):
    out_channels = 2048  # channels of the last feature level
    def __init__(self):
        super().__init__()
        self.body = resnet50()
retina = RetinaNet(backbone=MyBackbone(), num_classes=91)
Defensive patterns

Strategy: validation

Validate before calling

if not hasattr(backbone, "out_channels"):
    raise TypeError("backbone must define integer attribute out_channels")
out_channels = backbone.out_channels

Type guard

def is_valid_retinanet_backbone(backbone) -> bool:
    oc = getattr(backbone, "out_channels", None)
    return isinstance(oc, int) and oc > 0

Try / catch

try:
    model = RetinaNet(backbone=backbone, num_classes=num_classes)
except ValueError as e:
    if "out_channels" in str(e):
        backbone.out_channels = infer_out_channels(backbone)  # probe with dummy input
        model = RetinaNet(backbone=backbone, num_classes=num_classes)
    else:
        raise

Prevention

When it happens

Trigger: Instantiating RetinaNet(backbone=my_custom_cnn, ...) where my_custom_cnn class never defines self.out_channels; wrapping a backbone in a custom module that drops the attribute; using a plain torchvision resnet directly without the FPN helper.

Common situations: Swapping in a custom backbone (EfficientNet, Swin, etc.) copied from a classification repo; upgrading torchvision so backbone-builder APIs changed; writing a wrapper module around a backbone and forgetting to forward out_channels.

Related errors


AI-assisted analysis of WZMIAOMIAO/deep-learning-for-image-processing@1ec3fe6f37 (2026-08-30). Data as JSON: /api/errors/3a1356b420f14862. Report an issue: GitHub.