TensorFlow
binary classification
machine learning
loss function
model accuracy

Binary classification in TensorFlow, unexpected large values for loss and accuracy

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

In TensorFlow binary classification, wildly wrong-looking loss or accuracy values are usually signs of a configuration mismatch rather than proof that the optimizer is broken. The output layer, label encoding, loss function, and metric all have to agree on what a binary prediction means.

Start with the correct binary-classification setup

The most common pattern is:

  • one output unit
  • sigmoid activation
  • labels encoded as 0 and 1
  • binary cross-entropy loss
python
1import tensorflow as tf
2
3model = tf.keras.Sequential([
4    tf.keras.layers.Dense(16, activation="relu"),
5    tf.keras.layers.Dense(1, activation="sigmoid"),
6])
7
8model.compile(
9    optimizer="adam",
10    loss=tf.keras.losses.BinaryCrossentropy(),
11    metrics=[tf.keras.metrics.BinaryAccuracy()],
12)

With this setup, loss should usually be non-negative and accuracy should normally appear as a fraction between 0 and 1 unless you explicitly transform it elsewhere.

Common mismatch: logits versus probabilities

One frequent cause of strange loss values is mixing logits and probabilities.

These two combinations are both valid:

  1. sigmoid output plus BinaryCrossentropy(from_logits=False)
  2. linear output plus BinaryCrossentropy(from_logits=True)

What is invalid is using a sigmoid output and also telling the loss that the output is logits. That effectively applies the wrong math and can produce unstable training signals.

Correct logits-based version:

python
1model = tf.keras.Sequential([
2    tf.keras.layers.Dense(16, activation="relu"),
3    tf.keras.layers.Dense(1),
4])
5
6model.compile(
7    optimizer="adam",
8    loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
9    metrics=[tf.keras.metrics.BinaryAccuracy(threshold=0.0)],
10)

Choose one convention and stay consistent.

Check label encoding and shape

Binary classification expects labels that match the task. If your targets are strings, -1 and 1, one-hot vectors, or values like 1 and 2, metrics and loss can become misleading.

For the standard binary setup, your labels should look like this:

python
import numpy as np

y_train = np.array([0, 1, 1, 0, 1], dtype="float32")

Also verify the shape. If predictions have shape (batch_size, 1) and labels have an unexpected extra dimension or an incompatible dtype, TensorFlow may still run while the numbers stop making intuitive sense.

Accuracy can look wrong for reasons unrelated to loss

Loss and accuracy measure different things. It is possible to have:

  • a fairly large loss with decent accuracy
  • improving loss with nearly flat accuracy

That is not always a bug. Cross-entropy cares about confidence, while accuracy only cares about whether the thresholded class is correct.

For example, if the model predicts 0.51 for all positives and 0.49 for all negatives, accuracy can be high while loss is still not especially good because the model is barely confident.

What is more concerning is accuracy outside the expected range or values that explode immediately. That usually points to a data or metric setup issue.

Inspect the data pipeline too

Unexpected metrics also come from bad inputs:

  • labels shuffled out of alignment with features
  • feature scales causing unstable gradients
  • NaNs or infinities in the input
  • tiny batches that make the training log noisy

A quick diagnostic step is to overfit a tiny batch intentionally:

python
1x_small = x_train[:32]
2y_small = y_train[:32]
3
4history = model.fit(x_small, y_small, epochs=50, verbose=0)
5print(history.history["loss"][-1], history.history["binary_accuracy"][-1])

If the model cannot fit a tiny clean subset, the issue is usually configuration or data quality rather than generalization.

Common Pitfalls

The biggest mistake is mismatching sigmoid outputs with from_logits=True, or linear outputs with a loss that expects probabilities. Pick one convention and keep it consistent end to end.

Another mistake is using labels that are not properly encoded for binary classification. Values such as 1 and 2 or one-hot arrays can silently distort metrics if the rest of the pipeline expects simple 0 and 1 targets.

Developers also expect loss and accuracy to move in lockstep. They do not. Loss is sensitive to confidence, accuracy is threshold-based.

Finally, do not debug the optimizer before checking the raw data for NaNs, bad scaling, or misaligned features and labels.

Summary

  • In TensorFlow binary classification, the output layer, labels, and loss must follow one consistent convention.
  • Use either sigmoid plus normal binary cross-entropy or linear logits plus from_logits=True.
  • Keep labels encoded as 0 and 1 unless you intentionally use a different formulation.
  • Accuracy and loss measure different things, so they do not always move together.
  • If the numbers look absurd, inspect model configuration and data alignment before anything else.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design