keras-team/keras · error · ValueError

When class_id is provided, y_pred must be a 2D array with sh

Error message

When class_id is provided, y_pred must be a 2D array with shape (num_samples, num_classes), found shape: {y_pred.shape}

What it means

When update_confusion_matrix_variables() is called with class_id, it slices one class column out of y_pred, which requires a 2D prediction tensor of shape (num_samples, num_classes). If y_pred is rank 1 (for example after top_k filtering or with a single-output model), this ValueError is raised.

Source

Thrown at keras/src/metrics/metrics_utils.py:474

            f'Invalid keys: "{invalid_keys}". '
            f'Valid variable key options are: "{list(ConfusionMatrix)}"'
        )

    y_pred, y_true = squeeze_or_expand_to_same_rank(y_pred, y_true)
    if sample_weight is not None:
        sample_weight = ops.expand_dims(
            ops.cast(sample_weight, dtype=variable_dtype), axis=-1
        )
        _, sample_weight = squeeze_or_expand_to_same_rank(
            y_true, sample_weight, expand_rank_1=False
        )

    if top_k is not None:
        y_pred = _filter_top_k(y_pred, top_k)

    if class_id is not None:
        if len(y_pred.shape) == 1:
            raise ValueError(
                "When class_id is provided, y_pred must be a 2D array "
                "with shape (num_samples, num_classes), found shape: "
                f"{y_pred.shape}"
            )

        # Preserve dimension to match with sample_weight
        y_true = y_true[..., class_id, None]
        y_pred = y_pred[..., class_id, None]

    if thresholds_distributed_evenly:
        return _update_confusion_matrix_variables_optimized(
            variables_to_update,
            y_true,
            y_pred,
            thresholds,
            multi_label=multi_label,
            sample_weights=sample_weight,
            label_weights=label_weights,

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Reshape y_pred to (batch, 1) with keras.ops.expand_dims(y_pred, -1) before update_state, or make the model output 2D.
  2. For binary classification, drop class_id and use the default thresholded metric on the single output.
  3. If using top_k with class_id, verify the post-filter y_pred still has rank 2.

Example fix

# before
metric = keras.metrics.Precision(class_id=0)
metric.update_state(y_true, y_pred)  # y_pred shape (batch,)

# after
metric.update_state(y_true, keras.ops.expand_dims(y_pred, -1))  # (batch, 1)
Defensive patterns

Strategy: type-guard

Validate before calling

import keras.ops as ops
y_pred2 = ops.expand_dims(y_pred, -1) if len(y_pred.shape) == 1 else y_pred

Type guard

def is_rank2(x) -> bool:
    return len(getattr(x, 'shape', ())) == 2

Prevention

When it happens

Trigger: Calling with class_id=k while y_pred has rank 1, or combining top_k (which can reduce the prediction rank) with class_id on single-output models.

Common situations: Using Precision(class_id=1) or Recall(class_id=0) on a model whose output shape is (batch,) instead of (batch, num_classes) - typical for single-sigmoid-output binary classifiers.

Related errors


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