induwara.lk
induwara.lkAI · Machine learning

Huber Loss Calculator (Smooth L1 Loss)

Paste your predicted and actual values, choose a delta δ, and get the Huber loss and PyTorch Smooth L1 loss in your browser — with a per-element split of which residuals fall in the quadratic (MSE-like) region and which are clipped into the linear (MAE-like) region, plus MSE and MAE for comparison. Matches torch.nn.HuberLoss.

By Induwara AshinsanaUpdated Jul 12, 2026
Huber loss calculator

Your model's outputs. Comma, space or newline separated.

The ground-truth targets. Must match the predicted count.

Threshold between the quadratic and linear regions. Default 1.

Loss variant

Show Huber, PyTorch Smooth L1, or both side by side.

Reduction

mean and sum reduce to a scalar; none keeps the per-element vector.

δ presets
Examples
Huber loss (mean)
0.1875
δ = 1, N = 4
Smooth L1 (mean)
0.1875
β = 1
MSE (½·MSE if all quadratic)
0.375
0.5·MSE = 0.1875 = Huber mean
MAE (robust baseline)
0.5
Huber → MAE-like for large |a|
Significant figures

Region split at δ = 1

Quadratic |a| ≤ δ
4 / 4100%
Linear |a| > δ
0 / 40%

Your formula (δ = 1)

a = ŷ − y

Huber: L(a) = 0.5·a²  if |a| ≤ 1;  else 1·(|a| − 0.5)

Smooth L1: L(a) = 0.5·a²/1  if |a| < 1;  else |a| − 0.5

Identity: SmoothL1(β) = Huber(δ)/β  →  equal only when δ = β = 1

Cross-check. Recomputing every Smooth L1 element through the documented identity SmoothL1(β) = Huber(δ)/β reproduces the direct formula to within 0 (floating-point drift). The two independent code paths reconcile, as they must.

Per-element breakdown

#ŷya = ŷ−y|a|RegionHuberSmooth L1
12.53-0.50.5Quadratic0.1250.125
20-0.50.50.5Quadratic0.1250.125
32200Quadratic00
48711Quadratic0.50.5
Sum · mean (N = 4)0.75 · 0.18750.75 · 0.1875

Method: L_δ(a) = 0.5·a² if |a| ≤ δ, else δ·(|a| − 0.5·δ) with residual a = ŷ − y — Huber (1964); PyTorch HuberLoss / SmoothL1Loss. Smooth L1 cross-checked via SmoothL1(β) = Huber(δ)/β. No data leaves this page.

How it works

Huber loss was introduced by Peter J. Huber in “Robust Estimation of a Location Parameter” (1964) to combine the best of two common regression losses. Squared error (MSE) is smooth and easy to optimise but squares every mistake, so a single outlier can dominate training. Absolute error (MAE) resists outliers but has a kink at zero that makes its gradient jump. Huber loss is quadratic near zero and linear far from it, so it is both smooth and outlier-robust.

Work per element. For a predicted value ŷ and actual value y, the residual is a = ŷ − y. With threshold δ > 0, Huber loss is the piecewise function (Huber 1964; torch.nn.HuberLoss):

L(a) = 0.5·a²  if |a| ≤ δ   ·   δ·(|a| − 0.5·δ)  if |a| > δ

The two pieces meet at |a| = δ with matching value and slope, so the curve is continuous and differentiable there — that C¹ smoothness is what separates Huber from a raw clipped MAE. PyTorch's Smooth L1 loss is the same shape rescaled by its threshold β:

SmoothL1(a) = 0.5·a²/β  if |a| < β   ·   |a| − 0.5·β  if |a| ≥ β

  1. Region split. Each residual is tagged quadratic (|a| ≤ δ) or linear (|a| > δ). Sweeping δ moves points between the two, which is how you trade smoothness against outlier-robustness. The tool shows the count and percentage in each region.
  2. Reduction. Following PyTorch, mean returns (1/N)·Σ Lᵢ (the training objective), sum returns Σ Lᵢ, and none keeps the per-element vector.
  3. Comparison metrics. The same residuals also give MSE = (1/N)·Σ a² and MAE = (1/N)·Σ |a|, printed alongside so you can see Huber sitting between them.
  4. The Huber–MSE identity. When every residual is quadratic, the mean Huber loss equals exactly 0.5·MSE. The tool flags this and shows the half-MSE value so you can confirm it.

The documented relationship between the two losses is SmoothL1(β) = HuberLoss(δ = β) / β, so they coincide only when β = δ = 1. To keep results trustworthy the tool recomputes every Smooth L1 element through this identity and confirms it matches the direct formula to floating-point precision before displaying anything. All arithmetic runs client-side in double precision.

Worked examples

All residuals inside δ — quadratic region (δ = 1)

  1. Predicted [2.5, 0, 2, 8], Actual [3, −0.5, 2, 7]
  2. Residuals a = ŷ − y: −0.5, 0.5, 0, 1 → all |a| ≤ 1, so quadratic 0.5·a²
  3. Per-element loss: 0.125, 0.125, 0, 0.5
  4. Huber sum = 0.75, mean = 0.75 / 4 = 0.1875
  5. MSE = (0.25+0.25+0+1)/4 = 0.375 → 0.5·MSE = 0.1875 = Huber mean ✓
  6. MAE = (0.5+0.5+0+1)/4 = 0.5. δ=β=1 ⇒ Smooth L1 identical (mean 0.1875)

One outlier crosses into the linear region (δ = 1)

  1. Predicted [1, 2, 3], Actual [1, 2, 10]
  2. Residuals: 0, 0, −7 → |−7| = 7 > 1, so the third point is linear
  3. Linear loss: δ·(|a| − 0.5·δ) = 1·(7 − 0.5) = 6.5; other two = 0
  4. Huber sum = 6.5, mean = 6.5 / 3 = 2.16667
  5. MSE = 49/3 = 16.3333 (the outlier explodes it), MAE = 7/3 = 2.33333
  6. Huber (2.167) tracks MAE, not the inflated MSE — the robustness point

Huber ≠ Smooth L1 when δ = β = 2 — single residual a = 3

  1. Predicted [3], Actual [0] → residual a = 3, and |3| > δ = 2 (linear)
  2. Huber(δ=2) = δ·(|a| − 0.5·δ) = 2·(3 − 1) = 4.0
  3. Smooth L1(β=2) = |a| − 0.5·β = 3 − 1 = 2.0
  4. Ratio Huber / Smooth L1 = 4.0 / 2.0 = 2 = δ
  5. This confirms the identity SmoothL1(β) = Huber(δ)/β

Frequently asked questions

Sources & references

Related tools

Rate this tool
Be the first to rate

Comments & feedback

Spotted a bug or want an improvement? Tell us — our team reviews every comment, and good ideas get built. Comments are public and anonymous.

Found a bug, edge case, or want to suggest an improvement?

Email me at [email protected] — most fixes ship within 24 hours.