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
- Use in_chans=3 with standard RGB preprocessing (the supported pretrained path)
- Or use in_chans=1 with grayscale input, which the converter handles by summing filters
- 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
- Prefer RGB (3-channel) preprocessing when using pretrained ResNetV2 rec weights
- If you must use N channels, plan a custom stem init instead of the built-in converter
- Check checkpoint stem shape[1]==3 before attempting in_chans adaptation
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
- RecResizeImg.image_shape is required in rec inference.yml
- Recognition model session is not initialized.
- Unexpected recognition channels: ${String(channels)}
- Unexpected rec output dims: [${dims.join(", ")}]
- text_recognition_model_dir requires text_recognition_model_n
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/32830a61f2379318.
Report an issue: GitHub.