From c1d29ba459648bf8111e19e32988cb36ee8a94b0 Mon Sep 17 00:00:00 2001 From: AtomicVar Date: Tue, 30 Jan 2024 16:18:56 +0800 Subject: [PATCH] Add smooth l1 loss algorithm (#11239) --- machine_learning/loss_functions.py | 56 ++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/machine_learning/loss_functions.py b/machine_learning/loss_functions.py index f05fa0cbe..16e5a3278 100644 --- a/machine_learning/loss_functions.py +++ b/machine_learning/loss_functions.py @@ -573,6 +573,62 @@ def perplexity_loss( return np.mean(perp_losses) +def smooth_l1_loss(y_true: np.ndarray, y_pred: np.ndarray, beta: float = 1.0) -> float: + """ + Calculate the Smooth L1 Loss between y_true and y_pred. + + The Smooth L1 Loss is less sensitive to outliers than the L2 Loss and is often used + in regression problems, such as object detection. + + Smooth L1 Loss = + 0.5 * (x - y)^2 / beta, if |x - y| < beta + |x - y| - 0.5 * beta, otherwise + + Reference: + https://pytorch.org/docs/stable/generated/torch.nn.SmoothL1Loss.html + + Args: + y_true: Array of true values. + y_pred: Array of predicted values. + beta: Specifies the threshold at which to change between L1 and L2 loss. + + Returns: + The calculated Smooth L1 Loss between y_true and y_pred. + + Raises: + ValueError: If the length of the two arrays is not the same. + + >>> y_true = np.array([3, 5, 2, 7]) + >>> y_pred = np.array([2.9, 4.8, 2.1, 7.2]) + >>> smooth_l1_loss(y_true, y_pred, 1.0) + 0.012500000000000022 + + >>> y_true = np.array([2, 4, 6]) + >>> y_pred = np.array([1, 5, 7]) + >>> smooth_l1_loss(y_true, y_pred, 1.0) + 0.5 + + >>> y_true = np.array([1, 3, 5, 7]) + >>> y_pred = np.array([1, 3, 5, 7]) + >>> smooth_l1_loss(y_true, y_pred, 1.0) + 0.0 + + >>> y_true = np.array([1, 3, 5]) + >>> y_pred = np.array([1, 3, 5, 7]) + >>> smooth_l1_loss(y_true, y_pred, 1.0) + Traceback (most recent call last): + ... + ValueError: The length of the two arrays should be the same. + """ + + if len(y_true) != len(y_pred): + raise ValueError("The length of the two arrays should be the same.") + + diff = np.abs(y_true - y_pred) + loss = np.where(diff < beta, 0.5 * diff**2 / beta, diff - 0.5 * beta) + return np.mean(loss) + + if __name__ == "__main__": import doctest