PaddlePaddle/PaddleOCR · error · ValueError
normalize should be True if scale is passed
Error message
normalize should be True if scale is passed
What it means
PositionEmbeddingSine (used by the CAN head for contrastive character embedding) computes sine positional encodings optionally normalized to [0, scale]. The scale parameter only has meaning when cumulative coordinates are normalized, so passing scale with normalize=False is a contradictory configuration and __init__ raises ValueError('normalize should be True if scale is passed'). If scale is None it defaults to 2*pi.
Source
Thrown at ppocr/modeling/heads/rec_can_head.py:107
return x1, paddle.reshape(x, [b, self.out_channel, h, w])
"""
Attention Decoder
"""
class PositionEmbeddingSine(nn.Layer):
def __init__(
self, num_pos_feats=64, temperature=10000, normalize=False, scale=None
):
super().__init__()
self.num_pos_feats = num_pos_feats
self.temperature = temperature
self.normalize = normalize
if scale is not None and normalize is False:
raise ValueError("normalize should be True if scale is passed")
if scale is None:
scale = 2 * math.pi
self.scale = scale
def forward(self, x, mask):
y_embed = paddle.cumsum(mask, 1, dtype="float32")
x_embed = paddle.cumsum(mask, 2, dtype="float32")
if self.normalize:
eps = 1e-6
y_embed = y_embed / (y_embed[:, -1:, :] + eps) * self.scale
x_embed = x_embed / (x_embed[:, :, -1:] + eps) * self.scale
dim_t = paddle.arange(self.num_pos_feats, dtype="float32")
dim_d = paddle.expand(paddle.to_tensor(2), dim_t.shape)
dim_t = self.temperature ** (
2 * (dim_t / dim_d).astype("int64") / self.num_pos_feats
)
View on GitHub (pinned to 2661c7c0ef)
Solutions
- Add normalize=True when passing scale: PositionEmbeddingSine(..., normalize=True, scale=s)
- Or drop scale entirely and keep the default normalize=False behavior (scale defaults to 2*pi internally)
Example fix
# before PositionEmbeddingSine(num_pos_feats=64, scale=2 * math.pi) # ValueError # after PositionEmbeddingSine(num_pos_feats=64, normalize=True, scale=2 * math.pi)
Defensive patterns
Strategy: validation
Validate before calling
if scale is not None:
assert normalize is True, 'set normalize=True when passing scale to PositionEmbeddingSine'
PositionEmbeddingSine(num_pos_feats=64, normalize=normalize, scale=scale) Type guard
def valid_pos_embed_args(normalize: bool, scale) -> bool:
return scale is None or normalize is True Prevention
- Treat (normalize, scale) as coupled: setting scale implies normalize=True
- If unsure, omit scale and accept the internal default 2*pi
- Copy positional-embedding args from the shipped CAN head config verbatim
When it happens
Trigger: PositionEmbeddingSine(num_pos_feats=..., scale=100.0) without normalize=True; or a config that sets scale but leaves normalize at its default False.
Common situations: Tuning the CAN rec head config and adding a scale value copied from another codebase (DETR-style configs use normalize=True with scale=2*pi); forgetting the coupling between the two args.
Related errors
- Cannot use sin/cos positional encoding with odd dimension (g
- RecResizeImg.image_shape is required in rec inference.yml
- Unexpected recognition channels: ${String(channels)}
- OCR pipeline config text must decode to an object.
- OCR pipeline config must be an object or YAML text.
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/6cc9670b5da87779.
Report an issue: GitHub.