Skip to content

Commit cf0ce13

Browse files
committed
fix: avoid log(0) in KL divergence by filtering zero entries
Fixes #12233 - Filter out zero entries from y_true before computing logarithm - Add doctests demonstrating correct behavior with zeros - Mathematically correct per information theory conventions
1 parent 9d52683 commit cf0ce13

File tree

1 file changed

+15
-3
lines changed

1 file changed

+15
-3
lines changed

machine_learning/loss_functions.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,6 @@ def smooth_l1_loss(y_true: np.ndarray, y_pred: np.ndarray, beta: float = 1.0) ->
628628
loss = np.where(diff < beta, 0.5 * diff**2 / beta, diff - 0.5 * beta)
629629
return np.mean(loss)
630630

631-
632631
def kullback_leibler_divergence(y_true: np.ndarray, y_pred: np.ndarray) -> float:
633632
"""
634633
Calculate the Kullback-Leibler divergence (KL divergence) loss between true labels
@@ -653,16 +652,29 @@ def kullback_leibler_divergence(y_true: np.ndarray, y_pred: np.ndarray) -> float
653652
>>> predicted_probs = np.array([0.3, 0.3, 0.4, 0.5])
654653
>>> kullback_leibler_divergence(true_labels, predicted_probs)
655654
Traceback (most recent call last):
656-
...
655+
...
657656
ValueError: Input arrays must have the same length.
657+
>>> true_labels = np.array([0.0, 0.3, 0.7])
658+
>>> predicted_probs = np.array([0.1, 0.3, 0.6])
659+
>>> float(kullback_leibler_divergence(true_labels, predicted_probs))
660+
0.10790547587908085
661+
>>> true_labels = np.array([0.0, 0.0, 1.0])
662+
>>> predicted_probs = np.array([0.2, 0.3, 0.5])
663+
>>> float(kullback_leibler_divergence(true_labels, predicted_probs))
664+
0.6931471805599453
658665
"""
659666
if len(y_true) != len(y_pred):
660667
raise ValueError("Input arrays must have the same length.")
661668

662-
kl_loss = y_true * np.log(y_true / y_pred)
669+
# Filter out entries where y_true is 0 to avoid log(0)
670+
# By definition of KL divergence: 0 * log(0/q) = 0
671+
mask = y_true != 0
672+
kl_loss = y_true[mask] * np.log(y_true[mask] / y_pred[mask])
663673
return np.sum(kl_loss)
664674

665675

676+
677+
666678
if __name__ == "__main__":
667679
import doctest
668680

0 commit comments

Comments
 (0)