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

illegal stride value.

Error message

illegal stride value.

What it means

The MiniResNet-style InvertedResidual in mini_imagenet/model.py supports only stride 1 and 2, since a stride-1 branch requires doubled input channels (branch_features doubling) and stride 2 implements downsampling. Any other stride passed to __init__ raises ValueError immediately when building the model.

Source

Thrown at pytorch_classification/mini_imagenet/model.py:30

    # reshape
    # [batch_size, num_channels, height, width] -> [batch_size, groups, channels_per_group, height, width]
    x = x.view(batch_size, groups, channels_per_group, height, width)

    x = torch.transpose(x, 1, 2).contiguous()

    # flatten
    x = x.view(batch_size, -1, height, width)

    return x


class InvertedResidual(nn.Module):
    def __init__(self, input_c: int, output_c: int, stride: int):
        super(InvertedResidual, self).__init__()

        if stride not in [1, 2]:
            raise ValueError("illegal stride value.")
        self.stride = stride

        assert output_c % 2 == 0
        branch_features = output_c // 2
        # 当stride为1时,input_channel应该是branch_features的两倍
        # python中 '<<' 是位运算,可理解为计算×2的快速方法
        assert (self.stride != 1) or (input_c == branch_features << 1)

        if self.stride == 2:
            self.branch1 = nn.Sequential(
                self.depthwise_conv(input_c, input_c, kernel_s=3, stride=self.stride, padding=1),
                nn.BatchNorm2d(input_c),
                nn.Conv2d(input_c, branch_features, kernel_size=1, stride=1, padding=0, bias=False),
                nn.BatchNorm2d(branch_features),
                nn.ReLU(inplace=True)
            )
        else:
            self.branch1 = nn.Sequential()

View on GitHub (pinned to 1ec3fe6f37)

Solutions

  1. Restrict every InvertedResidual stride to 1 or 2 (use 2 for the first block of each downsampling stage)
  2. Clamp/validate the config before instantiation, e.g. stride = 2 if s > 1 else 1
  3. If larger downsampling is needed, stack multiple stride-2 blocks or add explicit MaxPool/conv-stride layers

Example fix

// before
layers.append(InvertedResidual(input_c, output_c, stride=4))
// after
layers.append(InvertedResidual(input_c, output_c, stride=2))  # repeat twice for 4x downsample
Defensive patterns

Strategy: validation

Validate before calling

cfg = [(input_c, output_c, s) for (input_c, output_c, s) in cfg if s in (1, 2)]
assert all(s in (1, 2) for _, _, s in cfg), 'stride must be 1 or 2'

Type guard

def valid_cfg(cfg) -> bool:
    return all(s in (1, 2) for (_, _, s) in cfg)

Try / catch

try:
    model = MobileNetV2(num_classes=100)
except ValueError as e:
    if 'illegal stride' in str(e):
        print('Sanitize your stride config:', e)
    raise

Prevention

When it happens

Trigger: Constructing the backbone with a per-stage config (like ResNet's layer list) where a stride value of 3, 4, or 0 is passed as InvertedResidual(input_c, output_c, stride=...), e.g. from a mis-edited cfg list or copied ResNet config using [1,2,4,8].

Common situations: Adapting MobileNetV2 definitions with custom strides; typos in the stride list; reusing ResNet50 cfg arrays where later stages use larger strides in the config not meant for this block.

Related errors


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