open-mmlab/mmdetection · error · ValueError

Either scales or octave_base_scale with scales_per_octave sh

Error message

Either scales or octave_base_scale with scales_per_octave should be set

What it means

AnchorGenerator needs anchor scales defined either explicitly via `scales` or implicitly via octave_base_scale together with scales_per_octave (RetinaNet-style octave scales). Providing neither raises ValueError in __init__.

Source

Thrown at mmdet/models/task_modules/prior_generators/anchor_generator.py:113

                           ] if base_sizes is None else base_sizes
        assert len(self.base_sizes) == len(self.strides), \
            'The number of strides should be the same as base sizes, got ' \
            f'{self.strides} and {self.base_sizes}'

        # calculate scales of anchors
        assert ((octave_base_scale is not None
                 and scales_per_octave is not None) ^ (scales is not None)), \
            'scales and octave_base_scale with scales_per_octave cannot' \
            ' be set at the same time'
        if scales is not None:
            self.scales = torch.Tensor(scales)
        elif octave_base_scale is not None and scales_per_octave is not None:
            octave_scales = np.array(
                [2**(i / scales_per_octave) for i in range(scales_per_octave)])
            scales = octave_scales * octave_base_scale
            self.scales = torch.Tensor(scales)
        else:
            raise ValueError('Either scales or octave_base_scale with '
                             'scales_per_octave should be set')

        self.octave_base_scale = octave_base_scale
        self.scales_per_octave = scales_per_octave
        self.ratios = torch.Tensor(ratios)
        self.scale_major = scale_major
        self.centers = centers
        self.center_offset = center_offset
        self.base_anchors = self.gen_base_anchors()
        self.use_box_type = use_box_type

    @property
    def num_base_anchors(self) -> List[int]:
        """list[int]: total number of base anchors in a feature grid"""
        return self.num_base_priors

    @property
    def num_base_priors(self) -> List[int]:

View on GitHub (pinned to cfd5d3a985)

Solutions

  1. Add explicit scales, e.g. scales=[8, 16, 32, 64]
  2. Or for FPN heads set octave_base_scale=4 and scales_per_octave=3 with strides [8,16,32,64,128] to derive scales
  3. Copy the anchor_generator block from a known-good config of the same detector type

Example fix

# before
anchor_generator=dict(type='AnchorGenerator', strides=[8,16,32], ratios=[0.5,1.0,2.0])
# after
anchor_generator=dict(type='AnchorGenerator', strides=[8,16,32], ratios=[0.5,1.0,2.0], scales=[8,16,32])
Defensive patterns

Strategy: validation

Validate before calling

has_scales = 'scales' in cfg and cfg['scales'] is not None
has_octave = cfg.get('octave_base_scale') is not None and cfg.get('scales_per_octave') is not None
assert has_scales or has_octave

Type guard

def anchor_scales_defined(c: dict) -> bool: return (c.get('scales') is not None) or (c.get('octave_base_scale') is not None and c.get('scales_per_octave') is not None)

Prevention

When it happens

Trigger: anchor_generator=dict(type='AnchorGenerator', ratios=[0.5,1.0,2.0]) with both scales and octave_base_scale omitted; or passing only scales_per_octave without octave_base_scale.

Common situations: Hand-writing anchor configs and forgetting the scale entry; partial deletion of a RetinaNet anchor generator config; passing octave_base_scale=None after tweaking.

Related errors


AI-assisted analysis of open-mmlab/mmdetection@cfd5d3a985 (2026-08-27). Data as JSON: /api/errors/cbe1e9fba207e8d6. Report an issue: GitHub.