keras-team/keras · error · ValueError

FBetaScore expects 2D inputs with shape (batch_size, output_

Error message

FBetaScore expects 2D inputs with shape (batch_size, output_dim). Received input shapes: y_pred.shape={y_pred_shape} and y_true.shape={y_true_shape}.

What it means

Raised from FBetaScore._build during update_state when y_pred or y_true is not rank 2. FBetaScore operates on one-hot/probability matrices of shape (batch_size, output_dim); rank-1 binary vectors or rank-3 tensors are rejected.

Source

Thrown at keras/src/metrics/f_score_metrics.py:124

            if threshold > 1.0 or threshold <= 0.0:
                raise ValueError(
                    "Invalid `threshold` argument value. "
                    "It should verify 0 < threshold <= 1. "
                    f"Received: threshold={threshold}"
                )

        self.average = average
        self.beta = beta
        self.threshold = threshold
        self.axis = None
        self._built = False

        if self.average != "micro":
            self.axis = 0

    def _build(self, y_true_shape, y_pred_shape):
        if len(y_pred_shape) != 2 or len(y_true_shape) != 2:
            raise ValueError(
                "FBetaScore expects 2D inputs with shape "
                "(batch_size, output_dim). Received input "
                f"shapes: y_pred.shape={y_pred_shape} and "
                f"y_true.shape={y_true_shape}."
            )
        if y_pred_shape[-1] is None or y_true_shape[-1] is None:
            raise ValueError(
                "FBetaScore expects 2D inputs with shape "
                "(batch_size, output_dim), with output_dim fully "
                "defined (not None). Received input "
                f"shapes: y_pred.shape={y_pred_shape} and "
                f"y_true.shape={y_true_shape}."
            )
        num_classes = y_pred_shape[-1]
        if self.average != "micro":
            init_shape = (num_classes,)
        else:
            init_shape = ()

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Expand dims for binary cases: keras.ops.expand_dims(y, -1).
  2. One-hot encode integer labels: keras.ops.one_hot(y_true, num_classes).
  3. End the model with Dense(num_classes, activation='softmax'/'sigmoid') so predictions are (batch, num_classes).

Example fix

# before
m.update_state(y_true, y_pred)  # both rank 1

# after
import keras.ops as ops
m.update_state(ops.expand_dims(y_true, -1), ops.expand_dims(y_pred, -1))
# or for multiclass:
m.update_state(ops.one_hot(y_true, num_classes), y_pred)
Defensive patterns

Strategy: validation

Validate before calling

import keras.ops as ops
if len(y_pred.shape) != 2:
    y_pred = ops.expand_dims(y_pred, -1)
if len(y_true.shape) != 2:
    y_true = ops.expand_dims(y_true, -1)

Type guard

def are_rank2(*ts) -> bool:
    return all(len(t.shape) == 2 for t in ts)

Prevention

When it happens

Trigger: Passing rank-1 y_true=[1,0,1,1] and y_pred=[0.8,0.2,0.9,0.7] to update_state; a model with rank-1 output; 3D sequence outputs without reshaping.

Common situations: Binary classification with single-column outputs; forgetting one-hot/to_categorical on integer labels; time-series outputs not flattened per timestep.

Related errors


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