Keras
machine learning
custom metrics
y_true
y_pred

What is y_true and y_pred when creating a custom metric in Keras?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When you write a custom metric in Keras, the framework passes two tensors into the metric function: y_true and y_pred. Those names are simple, but many bugs come from misunderstanding what they actually contain for a given model.

y_true is the ground-truth target batch from your dataset. y_pred is the model output for that same batch, usually before any manual post-processing you might perform outside the model.

What y_true Means

y_true is the target data that came from your labels. Its exact shape depends on the task and how the model was compiled.

Examples:

  • binary classification: shape often looks like (batch_size, 1) or (batch_size,)
  • multiclass classification with integer labels: shape often looks like (batch_size,)
  • one-hot multiclass targets: shape often looks like (batch_size, num_classes)
  • regression: shape often matches the regression output shape

In other words, y_true is not a special Keras abstraction. It is just the truth tensor for the current batch.

What y_pred Means

y_pred is the model’s output tensor for the same input batch. That does not always mean final hard class labels.

For example:

  • with a sigmoid output, y_pred may be probabilities between 0 and 1
  • with a softmax output, y_pred is usually class probabilities
  • with a linear regression output, y_pred is the raw predicted value

If your metric wants discrete class labels, you may need to threshold or use argmax yourself inside the metric.

A Simple Custom Metric Example

Here is a binary classification metric that computes the proportion of correct predictions after thresholding at 0.5:

python
1import keras
2import tensorflow as tf
3
4
5def binary_match_rate(y_true, y_pred):
6    y_true = tf.cast(y_true, tf.float32)
7    y_pred = tf.cast(y_pred > 0.5, tf.float32)
8    return tf.reduce_mean(tf.cast(tf.equal(y_true, y_pred), tf.float32))
9
10
11model = keras.Sequential(
12    [
13        keras.layers.Input(shape=(4,)),
14        keras.layers.Dense(1, activation="sigmoid"),
15    ]
16)
17
18model.compile(optimizer="adam", loss="binary_crossentropy", metrics=[binary_match_rate])

Notice that y_pred is not assumed to be already thresholded. The metric performs that conversion explicitly.

Multiclass Example

For multiclass classification with one-hot labels, the usual pattern is to compare argmax values.

python
1import tensorflow as tf
2
3
4def categorical_match_rate(y_true, y_pred):
5    true_ids = tf.argmax(y_true, axis=-1)
6    pred_ids = tf.argmax(y_pred, axis=-1)
7    return tf.reduce_mean(tf.cast(tf.equal(true_ids, pred_ids), tf.float32))

If your labels are sparse integers instead of one-hot vectors, then y_true may already contain class IDs and you would not apply argmax to it.

That is why understanding the label format matters before writing the metric.

Metrics See Batches, Not the Entire Dataset at Once

A custom metric function is usually called on batch-sized tensors during training and evaluation. That means the values of y_true and y_pred correspond to the current batch, not the full dataset in one tensor.

This matters because:

  • shape assumptions should be batch-aware
  • per-batch averages may differ slightly from global averages depending on how the metric is aggregated
  • debug prints should expect batch slices, not full training data

If you need stateful accumulation across batches, it is often better to subclass keras.metrics.Metric rather than use a one-off function.

Metric Functions Versus Loss Functions

The same two tensors appear in loss functions, but the role is different. A loss function drives optimization, while a metric is reported for monitoring.

That means a custom metric does not influence gradient updates unless you also use related logic inside the loss itself. Developers sometimes write a metric expecting it to change training behavior, which it does not.

Common Pitfalls

One common mistake is assuming y_pred already contains hard labels such as 0 or 1. In many models it contains probabilities or raw outputs that still need conversion.

Another issue is mismatching label format and metric logic. For example, using argmax on sparse integer labels is incorrect because those labels are already class IDs.

It is also easy to forget that metrics operate batch by batch. If you need dataset-level accumulation with custom state, use a metric class instead of a bare function.

Finally, avoid writing metrics with heavy Python-side logic. Metric code should stay tensor-friendly so it runs correctly inside Keras execution.

Summary

  • 'y_true is the ground-truth target tensor for the current batch.'
  • 'y_pred is the model output tensor for that same batch.'
  • 'y_pred often contains probabilities or raw outputs, not final class labels.'
  • The exact shapes depend on whether the task is binary classification, multiclass classification, or regression.
  • Good custom metrics start by matching their tensor logic to the actual label format and model output format.

Course illustration
Course illustration

All Rights Reserved.