@@ -250,6 +250,60 @@ def categorical_focal_cross_entropy(
250250 return np .mean (cfce_loss )
251251
252252
253+ def gaussian_negative_log_likelihood_loss (
254+ y_true : np .ndarray ,
255+ expectation_pred : np .ndarray ,
256+ var_pred : np .ndarray ,
257+ eps : float = 1e-6 ,
258+ ) -> float :
259+ """
260+ Calculate the negative log likelihood (NLL) loss between true labels and predicted
261+ Gaussian distributions.
262+
263+ NLL = -Σ(ln(1/(σ√(2π))) - 0.5 * ((y_true - μ)/σ)^2)
264+
265+ Reference: https://pytorch.org/docs/stable/generated/torch.nn.GaussianNLLLoss.html
266+
267+ Parameters:
268+ - y_true: True labels
269+ - expectation_pred: Predicted expectation (μ) of the Gaussian distribution
270+ - var_pred: Predicted variance (σ^2) of the Gaussian distribution
271+ - eps: Small constant to avoid numerical instability
272+
273+ Examples:
274+ >>> true_labels = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
275+ >>> expectation = np.array([0.8, 2.1, 2.9, 4.2, 5.2])
276+ >>> variance = np.array([0.1, 0.2, 0.3, 0.4, 0.5])
277+ >>> loss = gaussian_negative_log_likelihood_loss(true_labels, expectation, variance)
278+ >>> np.isclose(loss, -0.60621)
279+ True
280+
281+ >>> true_labels = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
282+ >>> expectation = np.array([0.8, 2.1, 2.9, 4.2, 5.2])
283+ >>> variance = np.array([0.1, 0.2, 0.3, 0.4])
284+ >>> gaussian_negative_log_likelihood_loss(true_labels, expectation, variance)
285+ Traceback (most recent call last):
286+ ...
287+ ValueError: Input arrays must have the same length.
288+ """
289+
290+ if (
291+ len (y_true ) != len (expectation_pred )
292+ or len (y_true ) != len (var_pred )
293+ or len (expectation_pred ) != len (var_pred )
294+ ):
295+ raise ValueError ("Input arrays must have the same length." )
296+
297+ # The constant term `0.5 * np.log(2 * np.pi)` is ignored since it doesn't affect the
298+ # optimization. PyTorch also ignores this term by default.
299+ # See https://pytorch.org/docs/stable/generated/torch.nn.GaussianNLLLoss.html
300+ loss_var = 0.5 * (np .log (np .maximum (var_pred , eps )))
301+ loss_exp = 0.5 * (np .square (y_true - expectation_pred ) / np .maximum (var_pred , eps ))
302+ loss = loss_var + loss_exp
303+
304+ return np .mean (loss )
305+
306+
253307def hinge_loss (y_true : np .ndarray , y_pred : np .ndarray ) -> float :
254308 """
255309 Calculate the mean hinge loss for between true labels and predicted probabilities
0 commit comments