keras-team/keras · error · ValueError

`y_pred` must have rank 2 when `multi_label=True`. Found ran

Error message

`y_pred` must have rank 2 when `multi_label=True`. Found rank {len(shape)}. Full shape received for `y_pred`: {shape}

What it means

Raised from AUC._build when multi_label=True but the y_pred shape is not rank 2. Multi-label AUC expects predictions of shape (batch_size, num_labels); rank-1 or rank-3+ tensors trigger this during __init__ (when num_labels is given) or the first update_state.

Source

Thrown at keras/src/metrics/confusion_metrics.py:1301

                self._build(shape)
        else:
            if num_labels:
                raise ValueError(
                    "`num_labels` is needed only when `multi_label` is True."
                )
            self._build(None)

    @property
    def thresholds(self):
        """The thresholds used for evaluating AUC."""
        return list(self._thresholds)

    def _build(self, shape):
        """Initialize TP, FP, TN, and FN tensors, given the shape of the
        data."""
        if self.multi_label:
            if len(shape) != 2:
                raise ValueError(
                    "`y_pred` must have rank 2 when `multi_label=True`. "
                    f"Found rank {len(shape)}. "
                    f"Full shape received for `y_pred`: {shape}"
                )
            self._num_labels = shape[1]
            variable_shape = [self.num_thresholds, self._num_labels]
        else:
            variable_shape = [self.num_thresholds]

        self._build_input_shape = shape
        # Create metric variables
        self.true_positives = self.add_variable(
            shape=variable_shape,
            initializer=initializers.Zeros(),
            name="true_positives",
        )
        self.false_positives = self.add_variable(
            shape=variable_shape,

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Make the model output 2D: end with Dense(num_labels, activation='sigmoid').
  2. Reshape y_pred/y_true to (batch, num_labels) before update_state.
  3. If the task is binary single-output, drop multi_label=True and use plain AUC.

Example fix

# before
x = keras.layers.GlobalAveragePooling2D()(x)
out = keras.layers.Activation('sigmoid')(x)  # missing Dense head

# after
x = keras.layers.GlobalAveragePooling2D()(x)
out = keras.layers.Dense(num_labels, activation='sigmoid')(x)
Defensive patterns

Strategy: validation

Validate before calling

assert y_pred.ndim == 2, f'multi_label AUC needs rank-2 y_pred, got {y_pred.shape}'

Type guard

def is_rank2(t) -> bool:
    return getattr(t, 'ndim', None) == 2 or len(getattr(t, 'shape', [])) == 2

Prevention

When it happens

Trigger: model.compile(metrics=[keras.metrics.AUC(multi_label=True, num_labels=3)]) with output shape (batch,) or (batch, 4, 5); rank-1 y_pred in update_state; missing final Dense layer.

Common situations: Missing Dense head so output is rank 1; conv outputs without pooling/flatten; data-pipeline shape changes after refactors.

Related errors


AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25). Data as JSON: /api/errors/dd77ad49a144c2f9. Report an issue: GitHub.