Custom loss function with weights in Keras
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Weighting a loss in Keras is a common way to tell the model that some mistakes matter more than others. The first question, though, should be whether you really need a custom loss; many weighting problems are already handled by class_weight or sample_weight, and using the built-in path is usually simpler and less error-prone.
When a Custom Weighted Loss Is Necessary
Use Keras built-in weighting when the rule is straightforward:
- '
class_weightfor class-level weighting in standard classification' - '
sample_weightwhen each training example has its own weight'
Use a custom loss when the weighting logic depends on tensor values inside the batch, on multiple outputs, or on a weighting rule that the built-in arguments cannot express cleanly.
The implementation rule is important: a Keras loss must use TensorFlow operations. If you use NumPy inside the loss, gradient computation will break because NumPy executes outside the TensorFlow graph.
Example: Weighted Binary Crossentropy
The following example increases the penalty for false negatives by multiplying the positive class term.
This example is fully differentiable because every operation is a TensorFlow op.
Per-Class Weighting for One-Hot Targets
For multi-class classification, a common pattern is to multiply the per-class crossentropy by a weight derived from the true class.
Here, the true class selects the relevant weight because y_true is one-hot encoded. If your labels are integer class ids instead, you would map those ids to weights differently.
Serialization Matters
If the model needs to be saved and loaded later, register the custom loss or pass it in custom_objects when loading. Forgetting that step is one of the most common reasons weighted-loss models fail to reload.
Using @tf.keras.utils.register_keras_serializable() is a good habit because it makes the loss easier to serialize in modern Keras workflows.
Prefer Simpler Built-In Weighting When It Fits
A lot of custom loss code is unnecessary. If your only goal is “class 1 should count three times more”, this may be enough:
That version is shorter, easier to read, and avoids mistakes in the manual loss formula.
Common Pitfalls
The biggest pitfall is using NumPy inside the loss function. Loss code must stay in TensorFlow so gradients can flow correctly.
Another mistake is returning a Python scalar or reducing the wrong dimension. A Keras loss should return a tensor whose aggregation behavior is consistent with the model setup.
A third issue is writing a custom loss for a problem already solved by class_weight or sample_weight. That adds maintenance cost with no real gain.
Summary
- Use
class_weightorsample_weightfirst when they match the problem. - Write a custom loss only when the weighting rule depends on tensor logic that built-in weighting cannot express.
- Keep the loss differentiable by using TensorFlow operations, not NumPy.
- Register custom losses if the model needs to be saved and loaded later.
- Validate the formula on a small example before trusting a long training run.

