Skip to content

Commit d740bb0

Browse files
ZJUGuoShuaicclauss
andauthored
Add Gaussian negative log likelihood loss algorithm (#11263)
* Add Gaussian negative log likelihood loss algorithm * Fix boolean conversion in Gaussian NLL loss example --------- Co-authored-by: Christian Clauss <cclauss@me.com>
1 parent 5ed60e7 commit d740bb0

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

machine_learning/loss_functions.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# ruff: noqa: RUF002 -- ambiguous-unicode-character-docstring
2+
13
import numpy as np
24

35

@@ -302,6 +304,60 @@ def categorical_focal_cross_entropy(
302304
return np.mean(cfce_loss)
303305

304306

307+
def gaussian_negative_log_likelihood_loss(
308+
y_true: np.ndarray,
309+
expectation_pred: np.ndarray,
310+
var_pred: np.ndarray,
311+
eps: float = 1e-6,
312+
) -> float:
313+
"""
314+
Calculate the negative log likelihood (NLL) loss between true labels and predicted
315+
Gaussian distributions.
316+
317+
NLL = -Σ(ln(1/(σ√(2π))) - 0.5 * ((y_true - μ)/σ)^2)
318+
319+
Reference: https://pytorch.org/docs/stable/generated/torch.nn.GaussianNLLLoss.html
320+
321+
Parameters:
322+
- y_true: True labels
323+
- expectation_pred: Predicted expectation (μ) of the Gaussian distribution
324+
- var_pred: Predicted variance (σ^2) of the Gaussian distribution
325+
- eps: Small constant to avoid numerical instability
326+
327+
Examples:
328+
>>> true_labels = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
329+
>>> expectation = np.array([0.8, 2.1, 2.9, 4.2, 5.2])
330+
>>> variance = np.array([0.1, 0.2, 0.3, 0.4, 0.5])
331+
>>> loss = gaussian_negative_log_likelihood_loss(true_labels, expectation, variance)
332+
>>> bool(np.isclose(loss, -0.60621))
333+
True
334+
335+
>>> true_labels = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
336+
>>> expectation = np.array([0.8, 2.1, 2.9, 4.2, 5.2])
337+
>>> variance = np.array([0.1, 0.2, 0.3, 0.4])
338+
>>> gaussian_negative_log_likelihood_loss(true_labels, expectation, variance)
339+
Traceback (most recent call last):
340+
...
341+
ValueError: Input arrays must have the same length.
342+
"""
343+
344+
if (
345+
len(y_true) != len(expectation_pred)
346+
or len(y_true) != len(var_pred)
347+
or len(expectation_pred) != len(var_pred)
348+
):
349+
raise ValueError("Input arrays must have the same length.")
350+
351+
# The constant term `0.5 * np.log(2 * np.pi)` is ignored since it doesn't affect the
352+
# optimization. PyTorch also ignores this term by default.
353+
# See https://pytorch.org/docs/stable/generated/torch.nn.GaussianNLLLoss.html
354+
loss_var = 0.5 * (np.log(np.maximum(var_pred, eps)))
355+
loss_exp = 0.5 * (np.square(y_true - expectation_pred) / np.maximum(var_pred, eps))
356+
loss = loss_var + loss_exp
357+
358+
return np.mean(loss)
359+
360+
305361
def hinge_loss(y_true: np.ndarray, y_pred: np.ndarray) -> float:
306362
"""
307363
Calculate the mean hinge loss for between true labels and predicted probabilities

0 commit comments

Comments
 (0)