Skip to content

Add smooth l1 loss algorithm #11239

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 30, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions machine_learning/loss_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,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

Expand Down