PaddlePaddle/PaddleOCR · error · NotImplementedError

Weight format not supported by conversion.

Error message

Weight format not supported by conversion.

What it means

This is weight-conversion helper logic (adapt_patch_embed-style, in_chans handling for ResNetV2-family rec backbones) that adapts a pretrained 3-channel stem conv to a different input channel count. For in_chans==1 it can sum/replicate filters, but for any other in_chans != 3 the original weight must have exactly I==3 input filters (conv_weight.shape[1]); otherwise conversion is undefined and NotImplementedError is raised.

Source

Thrown at ppocr/modeling/backbones/rec_resnetv2.py:633


def adapt_input_conv(in_chans, conv_weight):
    conv_type = conv_weight.dtype
    conv_weight = (
        conv_weight.float()
    )  # Some weights are in torch.half, ensure it's float for sum on CPU
    O, I, J, K = conv_weight.shape
    if in_chans == 1:
        if I > 3:
            assert conv_weight.shape[1] % 3 == 0
            # For models with space2depth stems
            conv_weight = conv_weight.reshape(O, I // 3, 3, J, K)
            conv_weight = conv_weight.sum(dim=2, keepdim=False)
        else:
            conv_weight = conv_weight.sum(dim=1, keepdim=True)
    elif in_chans != 3:
        if I != 3:
            raise NotImplementedError("Weight format not supported by conversion.")
        else:
            # NOTE this strategy should be better than random init, but there could be other combinations of
            # the original RGB input layer weights that'd work better for specific cases.
            repeat = int(math.ceil(in_chans / 3))
            conv_weight = conv_weight.repeat(1, repeat, 1, 1)[:, :in_chans, :, :]
            conv_weight *= 3 / float(in_chans)
    conv_weight = conv_weight.to(conv_type)
    return conv_weight


def named_apply(
    fn: Callable, module: nn.Layer, name="", depth_first=True, include_root=False
) -> nn.Layer:
    if not depth_first and include_root:
        fn(module=module, name=name)
    for child_name, child_module in module.named_children():
        child_name = ".".join((name, child_name)) if name else child_name
        named_apply(

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Use in_chans=3 with standard RGB preprocessing (the supported pretrained path)
  2. Or use in_chans=1 with grayscale input, which the converter handles by summing filters
  3. For other channel counts, provide a stem weight with exactly 3 input filters, or write a custom adapter that initializes the new stem (e.g. average or repeat of the 3-channel kernels) instead of relying on this helper

Example fix

# before
create_model(pretrained=True, in_chans=4)  # checkpoint stem I==6 -> NotImplementedError

# after
create_model(pretrained=True, in_chans=3)  # keep RGB; or in_chans=1 for grayscale
Defensive patterns

Strategy: validation

Validate before calling

assert in_chans in (1, 3), f'stem-weight conversion supports in_chans 1 or 3, got {in_chans}'

Type guard

def convertible_in_chans(c: int) -> bool:
    return c in (1, 3)

Prevention

When it happens

Trigger: Loading a pretrained checkpoint whose first conv expects a channel count other than 3 while requesting in_chans other than 1 or 3 — e.g. in_chans=4 with a checkpoint stem built for 6-channel input (I=6).

Common situations: Fine-tuning rec ResNetV2 variants on multi-spectral/RGBA or concatenated inputs; using a checkpoint from a different model family whose stem layout doesn't match the 3-channel assumption of the adapter.

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/32830a61f2379318. Report an issue: GitHub.