PaddlePaddle/PaddleOCR · error · TypeError

The type of 'eta_min' in 'CosineAnnealingDecay' must be 'flo

Error message

The type of 'eta_min' in 'CosineAnnealingDecay' must be 'float, int', but received %s.

What it means

TypeError from TwoStepCosineDecay.__init__ when eta_min is neither float nor int. Unlike T_max1/T_max2, this check accepts both numeric types, so it only fires for genuinely non-numeric input such as strings or None.

Source

Thrown at ppocr/optimizer/lr_scheduler.py:183

        return computed_lr


class TwoStepCosineDecay(LRScheduler):
    def __init__(
        self, learning_rate, T_max1, T_max2, eta_min=0, last_epoch=-1, verbose=False
    ):
        if not isinstance(T_max1, int):
            raise TypeError(
                "The type of 'T_max1' in 'CosineAnnealingDecay' must be 'int', but received %s."
                % type(T_max1)
            )
        if not isinstance(T_max2, int):
            raise TypeError(
                "The type of 'T_max2' in 'CosineAnnealingDecay' must be 'int', but received %s."
                % type(T_max2)
            )
        if not isinstance(eta_min, (float, int)):
            raise TypeError(
                "The type of 'eta_min' in 'CosineAnnealingDecay' must be 'float, int', but received %s."
                % type(eta_min)
            )
        assert T_max1 > 0 and isinstance(
            T_max1, int
        ), " 'T_max1' must be a positive integer."
        assert T_max2 > 0 and isinstance(
            T_max2, int
        ), " 'T_max1' must be a positive integer."
        self.T_max1 = T_max1
        self.T_max2 = T_max2
        self.eta_min = float(eta_min)
        super(TwoStepCosineDecay, self).__init__(learning_rate, last_epoch, verbose)

    def get_lr(self):
        if self.last_epoch <= self.T_max1:
            if self.last_epoch == 0:
                return self.base_lr

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Provide eta_min as a number: eta_min=1e-5 or eta_min: 0.0 in YAML (unquoted).
  2. If the value may arrive as a string, coerce first: float(eta_min).
  3. If the key is optional in your pipeline, default it explicitly to 0 rather than None.

Example fix

# before
TwoStepCosineDecay(learning_rate=lr, T_max1=270, T_max2=30, eta_min="0.0")  # string

# after
TwoStepCosineDecay(learning_rate=lr, T_max1=270, T_max2=30, eta_min=0.0)
Defensive patterns

Strategy: type-guard

Validate before calling

eta_min = float(eta_min if eta_min is not None else 0)

Type guard

def is_numeric_eta_min(v) -> bool:
    return isinstance(v, (int, float)) and not isinstance(v, bool)

Prevention

When it happens

Trigger: Passing eta_min as a quoted string from config ("0.0"), None when the config key is absent and defaulted incorrectly, or a numpy array/object.

Common situations: YAML configs with quoted numerics; configs templated from JSON where all values became strings; passing optimizer groups or dicts instead of scalars.

Related errors


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