TensorFlow
tf.metrics.accuracy
machine learning
accuracy calculation
deep learning

How to properly use tf.metrics.accuracy?

Master System Design with Codemia

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

Introduction

Accuracy sounds simple, but TensorFlow exposes several metric APIs and they are not interchangeable. The correct choice depends on whether you are in legacy graph-mode TensorFlow or modern TensorFlow 2, and on whether your labels are binary, sparse integers, or one-hot encoded. Most accuracy bugs come from using the wrong metric for the prediction format.

Prefer Keras Metrics in TensorFlow 2

In modern TensorFlow, the usual choice is one of the Keras metric classes:

  • 'BinaryAccuracy'
  • 'CategoricalAccuracy'
  • 'SparseCategoricalAccuracy'
  • 'Accuracy for direct equality checks'

Binary example:

python
1import tensorflow as tf
2
3y_true = tf.constant([1, 0, 1, 1], dtype=tf.int32)
4y_pred = tf.constant([0.9, 0.2, 0.4, 0.8], dtype=tf.float32)
5
6metric = tf.keras.metrics.BinaryAccuracy(threshold=0.5)
7metric.update_state(y_true, y_pred)
8
9print(float(metric.result().numpy()))

This works because the predictions are probabilities and the metric knows how to threshold them.

Match the Metric to the Label Format

For multiclass classification, the label encoding determines the right metric.

Sparse integer labels:

python
1import tensorflow as tf
2
3y_true = tf.constant([2, 0, 1], dtype=tf.int32)
4y_pred = tf.constant([
5    [0.1, 0.2, 0.7],
6    [0.8, 0.1, 0.1],
7    [0.2, 0.6, 0.2],
8], dtype=tf.float32)
9
10metric = tf.keras.metrics.SparseCategoricalAccuracy()
11metric.update_state(y_true, y_pred)
12
13print(float(metric.result().numpy()))

One-hot labels:

python
1y_true = tf.constant([
2    [0, 0, 1],
3    [1, 0, 0],
4    [0, 1, 0],
5], dtype=tf.float32)
6
7metric = tf.keras.metrics.CategoricalAccuracy()
8metric.update_state(y_true, y_pred)
9print(float(metric.result().numpy()))

If you mix these up, the metric result may be meaningless even though the code runs.

Use Metrics in model.compile

When training with Keras, the cleanest path is to supply the metric during compile.

python
1model.compile(
2    optimizer="adam",
3    loss="sparse_categorical_crossentropy",
4    metrics=[tf.keras.metrics.SparseCategoricalAccuracy(name="acc")],
5)

That keeps training, validation, and logging aligned with the model’s output and label format.

Reset State in Custom Loops

Metric objects are stateful. In custom training loops, you must reset them at the right boundary, usually once per epoch or evaluation run.

python
1train_acc = tf.keras.metrics.SparseCategoricalAccuracy()
2
3for epoch in range(3):
4    train_acc.reset_state()
5
6    for x_batch, y_batch in dataset:
7        logits = model(x_batch, training=False)
8        train_acc.update_state(y_batch, logits)
9
10    print("epoch", epoch, "accuracy", float(train_acc.result().numpy()))

If you forget to reset, later epochs accumulate earlier state and the reported accuracy becomes misleading.

What About tf.metrics.accuracy

Older TensorFlow 1 style code often used tf.metrics.accuracy, which returned a value tensor and an update op in graph mode. That API made sense in session-based workflows but is not the normal choice in TensorFlow 2.

Legacy-style example:

python
1import tensorflow as tf
2
3labels = tf.constant([1, 0, 1], dtype=tf.int32)
4preds = tf.constant([1, 1, 1], dtype=tf.int32)
5
6value, update = tf.compat.v1.metrics.accuracy(labels=labels, predictions=preds)
7print(value, update)

If you are maintaining graph-mode code, that compatibility API may still matter. For new code, prefer tf.keras.metrics.

Accuracy Is Not Always the Best Metric

Accuracy is convenient, but it can hide important failures, especially on imbalanced datasets. A model that predicts the majority class well can report strong accuracy while performing badly on the cases you actually care about.

Consider tracking additional metrics such as:

  • precision
  • recall
  • AUC
  • confusion matrix summaries

Accuracy is still useful, but it should match the problem rather than being used automatically.

Debug Metric Results with Tiny Batches

If the reported value looks suspicious, test the metric on a tiny hand-written batch where you already know the answer.

python
1import tensorflow as tf
2
3y_true = tf.constant([0, 1, 1, 0], dtype=tf.int32)
4y_pred = tf.constant([0.1, 0.9, 0.8, 0.4], dtype=tf.float32)
5
6metric = tf.keras.metrics.BinaryAccuracy(threshold=0.5)
7metric.update_state(y_true, y_pred)
8print(float(metric.result().numpy()))

That kind of sanity check catches label-encoding mistakes quickly.

Common Pitfalls

The biggest mistake is using Accuracy for probabilistic outputs when a task-specific metric is needed. Accuracy is a direct equality metric, so it is often the wrong tool for logits or probability vectors.

Another issue is mixing sparse integer labels with CategoricalAccuracy, or one-hot labels with SparseCategoricalAccuracy.

Developers also often forget that metric objects keep state across updates, which makes custom-loop reporting incorrect if reset_state is skipped.

Summary

  • In TensorFlow 2, prefer tf.keras.metrics over legacy tf.metrics.accuracy.
  • Choose the metric based on label encoding and prediction format.
  • Reset metric state at the correct boundary in custom loops.
  • Verify metric behavior with a tiny known batch when results look wrong.
  • Accuracy is useful, but it should not automatically be the only metric you track.

Course illustration
Course illustration

All Rights Reserved.