open-mmlab/mmdetection · error · ValueError
NUM_BRANCHES({num_branches}) != NUM_INCHANNELS({len(in_chann
Error message
NUM_BRANCHES({num_branches}) != NUM_INCHANNELS({len(in_channels)}) What it means
The third HRNet branch check: len(in_channels) must equal num_branches, since in_channels lists the input channel count feeding each branch of the stage. Mismatch raises ValueError naming NUM_INCHANNELS.
Source
Thrown at mmdet/models/backbones/hrnet.py:64
self.fuse_layers = self._make_fuse_layers()
self.relu = nn.ReLU(inplace=False)
def _check_branches(self, num_branches, num_blocks, in_channels,
num_channels):
if num_branches != len(num_blocks):
error_msg = f'NUM_BRANCHES({num_branches}) ' \
f'!= NUM_BLOCKS({len(num_blocks)})'
raise ValueError(error_msg)
if num_branches != len(num_channels):
error_msg = f'NUM_BRANCHES({num_branches}) ' \
f'!= NUM_CHANNELS({len(num_channels)})'
raise ValueError(error_msg)
if num_branches != len(in_channels):
error_msg = f'NUM_BRANCHES({num_branches}) ' \
f'!= NUM_INCHANNELS({len(in_channels)})'
raise ValueError(error_msg)
def _make_one_branch(self,
branch_index,
block,
num_blocks,
num_channels,
stride=1):
downsample = None
if stride != 1 or \
self.in_channels[branch_index] != \
num_channels[branch_index] * block.expansion:
downsample = nn.Sequential(
build_conv_layer(
self.conv_cfg,
self.in_channels[branch_index],
num_channels[branch_index] * block.expansion,
kernel_size=1,
stride=stride,View on GitHub (pinned to cfd5d3a985)
Solutions
- Set in_channels of stageN equal (as a list) to num_channels of stage(N-1), and its length equal to num_branches
- Cross-check every stage dict: num_branches, num_blocks, num_channels, in_channels lengths must all agree
- Start from an official HRNet config and adjust widths consistently across stages
Example fix
# before stage2=dict(num_branches=2, num_blocks=[4,4], num_channels=[48,96], in_channels=[64]) # after stage2=dict(num_branches=2, num_blocks=[4,4], num_channels=[48,96], in_channels=[64,128])
Defensive patterns
Strategy: validation
Validate before calling
stages = list(extra.values())
for prev, cur in zip(stages, stages[1:]):
assert cur['num_branches'] == len(cur['in_channels']) == len(prev['num_channels']) Type guard
def inchannels_ok(stage: dict) -> bool:
return stage['num_branches'] == len(stage['in_channels']) Prevention
- Set stageN in_channels = stage(N-1) num_channels
- Never edit one stage's widths in isolation
- Chain in_channels/num_channels across stages
When it happens
Trigger: num_branches=4 with in_channels=[32,64,128] (len 3); stage2 in_channels not matching stage1's num_channels output; hand-editing multi-stage extra dicts.
Common situations: Changing an earlier stage's num_channels without updating the next stage's in_channels; building HRNet from scratch instead of from a reference config.
Related errors
- NUM_BRANCHES({num_branches}) != NUM_BLOCKS({len(num_blocks)}
- NUM_BRANCHES({num_branches}) != NUM_CHANNELS({len(num_channe
- type must be a str or valid type, but got {type(obj_type)}
- RandomCenterCropPad only support two testing pad mode:logica
- Not supported YouTubeVIS datasetversion: {dataset_version}
AI-assisted analysis of open-mmlab/mmdetection@cfd5d3a985 (2026-08-27).
Data as JSON: /api/errors/d1ec99ed3a701f71.
Report an issue: GitHub.