@@ -629,13 +629,15 @@ def smooth_l1_loss(y_true: np.ndarray, y_pred: np.ndarray, beta: float = 1.0) ->
629
629
return np .mean (loss )
630
630
631
631
632
- def kullback_leibler_divergence (y_true : np .ndarray , y_pred : np .ndarray ) -> float :
632
+ def kullback_leibler_divergence (
633
+ y_true : np .ndarray , y_pred : np .ndarray , epsilon : float = 1e-10
634
+ ) -> float :
633
635
"""
634
636
Calculate the Kullback-Leibler divergence (KL divergence) loss between true labels
635
637
and predicted probabilities.
636
638
637
- KL divergence loss quantifies dissimilarity between true labels and predicted
638
- probabilities. It's often used in training generative models.
639
+ KL divergence loss quantifies the dissimilarity between true labels and predicted
640
+ probabilities. It is often used in training generative models.
639
641
640
642
KL = Σ(y_true * ln(y_true / y_pred))
641
643
@@ -649,6 +651,7 @@ def kullback_leibler_divergence(y_true: np.ndarray, y_pred: np.ndarray) -> float
649
651
>>> predicted_probs = np.array([0.3, 0.3, 0.4])
650
652
>>> float(kullback_leibler_divergence(true_labels, predicted_probs))
651
653
0.030478754035472025
654
+
652
655
>>> true_labels = np.array([0.2, 0.3, 0.5])
653
656
>>> predicted_probs = np.array([0.3, 0.3, 0.4, 0.5])
654
657
>>> kullback_leibler_divergence(true_labels, predicted_probs)
@@ -659,7 +662,13 @@ def kullback_leibler_divergence(y_true: np.ndarray, y_pred: np.ndarray) -> float
659
662
if len (y_true ) != len (y_pred ):
660
663
raise ValueError ("Input arrays must have the same length." )
661
664
662
- kl_loss = y_true * np .log (y_true / y_pred )
665
+ # negligible epsilon to avoid issues with log(0) or division by zero
666
+ epsilon = 1e-10
667
+ y_pred = np .clip (y_pred , epsilon , None )
668
+
669
+ # calculate KL divergence only where y_true is not zero
670
+ kl_loss = np .where (y_true != 0 , y_true * np .log (y_true / y_pred ), 0.0 )
671
+
663
672
return np .sum (kl_loss )
664
673
665
674
0 commit comments