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

the backbone not has attribute: out_channel

Error message

the backbone not has attribute: out_channel

What it means

After the None check, SSD300 verifies the backbone exposes out_channels, needed by _build_additional_features to size extra conv layers. A backbone without this attribute (e.g. a raw resnet50 module without FPN wrapping) raises this Exception. Message says 'out_channel' but the attribute checked is 'out_channels'.

Source

Thrown at pytorch_object_detection/ssd/src/ssd_model.py:38

        conv4_block1 = self.feature_extractor[-1][0]

        # 修改conv4_block1的步距,从2->1
        conv4_block1.conv1.stride = (1, 1)
        conv4_block1.conv2.stride = (1, 1)
        conv4_block1.downsample[0].stride = (1, 1)

    def forward(self, x):
        x = self.feature_extractor(x)
        return x


class SSD300(nn.Module):
    def __init__(self, backbone=None, num_classes=21):
        super(SSD300, self).__init__()
        if backbone is None:
            raise Exception("backbone is None")
        if not hasattr(backbone, "out_channels"):
            raise Exception("the backbone not has attribute: out_channel")
        self.feature_extractor = backbone

        self.num_classes = num_classes
        # out_channels = [1024, 512, 512, 256, 256, 256] for resnet50
        self._build_additional_features(self.feature_extractor.out_channels)
        self.num_defaults = [4, 6, 6, 6, 4, 4]
        location_extractors = []
        confidence_extractors = []

        # out_channels = [1024, 512, 512, 256, 256, 256] for resnet50
        for nd, oc in zip(self.num_defaults, self.feature_extractor.out_channels):
            # nd is number_default_boxes, oc is output_channel
            location_extractors.append(nn.Conv2d(oc, nd * 4, kernel_size=3, padding=1))
            confidence_extractors.append(nn.Conv2d(oc, nd * self.num_classes, kernel_size=3, padding=1))

        self.loc = nn.ModuleList(location_extractors)
        self.conf = nn.ModuleList(confidence_extractors)
        self._init_weights()

View on GitHub (pinned to 1ec3fe6f37)

Solutions

  1. Wrap the CNN with resnet50_fpn_backbone() which adds an FPN exposing out_channels
  2. Set self.out_channels on your custom backbone (list of per-feature-map channel widths) and ensure hasattr passes
  3. Verify the object you pass is the wrapped backbone, not the raw torchvision model

Example fix

// before
backbone = resnet50(pretrained=True)
model = SSD300(backbone=backbone, num_classes=21)
// after
from torchvision.models.detection.backbone_utils import resnet_fpn_backbone
backbone = resnet_fpn_backbone('resnet50', pretrained=True)  # has out_channels
model = SSD300(backbone=backbone, num_classes=21)
Defensive patterns

Strategy: type-guard

Validate before calling

assert hasattr(backbone, 'out_channels'), 'backbone must expose out_channels (use an FPN-wrapped backbone)'

Type guard

def has_out_channels(obj) -> bool:
    return hasattr(obj, 'out_channels')

Try / catch

try:
    model = SSD300(backbone=backbone, num_classes=21)
except Exception as e:
    print(f'Backbone interface mismatch: {e}; wrap with resnet_fpn_backbone')

Prevention

When it happens

Trigger: Passing a plain torchvision resnet50 model directly (it lacks out_channels) instead of a wrapped FPN backbone; using a custom backbone whose only_out attribute is named differently; passing None-adjacent objects like a ModuleList of layers.

Common situations: Building SSD from torchvision models without the resnet50_fpn_backbone wrapper; custom feature extractors forgetting to set self.out_channels; mixing code from tutorial versions where the wrapper was implicit.

Related errors


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