# scipy.special.huber

scipy.special.huber(delta, r, out=None) = <ufunc 'huber'>

  Huber loss function.

  \[\begin{split}\text{huber}(\delta, r) = \begin{cases} \infty & \delta < 0 \\ \frac{1}{2}r^2 & 0 \le \delta, | r | \le \delta \\ \delta ( |r| - \frac{1}{2}\delta ) & \text{otherwise} \end{cases}\end{split}\]
  Parameters:
    delta ndarray

      Input array, indicating the quadratic vs. linear loss changepoint.

    r ndarray

      Input array, possibly representing residuals.

    out ndarray, optional

      Optional output array for the function values

  Returns:
    scalar or ndarray

      The computed Huber loss function values.

  See also

  `pseudo_huber`

    smooth approximation of this function

  Notes

  `huber` is useful as a loss function in robust statistics or machine learning to reduce the influence of outliers as compared to the common squared error loss, residuals with a magnitude higher than delta are not squared [1].

  Typically, r represents residuals, the difference between a model prediction and data. Then, for \(|r|\leq\delta\), `huber` resembles the squared error and for \(|r|>\delta\) the absolute error. This way, the Huber loss often achieves a fast convergence in model fitting for small residuals like the squared error loss function and still reduces the influence of outliers (\(|r|>\delta\)) like the absolute error loss. As \(\delta\) is the cutoff between squared and absolute error regimes, it has to be tuned carefully for each problem. `huber` is also convex, making it suitable for gradient based optimization.

  New in version 0.15.0.

  References

  [1]

  Peter Huber. “Robust Estimation of a Location Parameter”, 1964. Annals of Statistics. 53 (1): 73 - 101.

  Examples

  Import all necessary modules.

      >>> import numpy as np
      >>> from scipy.special import huber
      >>> import matplotlib.pyplot as plt

  Compute the function for `delta=1` at `r=2`

      >>> huber(1., 2.)
      1.5

  Compute the function for different delta by providing a NumPy array or list for delta.

      >>> huber([1., 3., 5.], 4.)
      array([3.5, 7.5, 8. ])

  Compute the function at different points by providing a NumPy array or list for r.

      >>> huber(2., np.array([1., 1.5, 3.]))
      array([0.5  , 1.125, 4.   ])

  The function can be calculated for different delta and r by providing arrays for both with compatible shapes for broadcasting.

      >>> r = np.array([1., 2.5, 8., 10.])
      >>> deltas = np.array([[1.], [5.], [9.]])
      >>> print(r.shape, deltas.shape)
      (4,) (3, 1)

      >>> huber(deltas, r)
      array([[ 0.5  ,  2.   ,  7.5  ,  9.5  ],
             [ 0.5  ,  3.125, 27.5  , 37.5  ],
             [ 0.5  ,  3.125, 32.   , 49.5  ]])

  Plot the function for different delta.

      >>> x = np.linspace(-4, 4, 500)
      >>> deltas = [1, 2, 3]
      >>> linestyles = ["dashed", "dotted", "dashdot"]
      >>> fig, ax = plt.subplots()
      >>> combined_plot_parameters = list(zip(deltas, linestyles))
      >>> for delta, style in combined_plot_parameters:
      ...     ax.plot(x, huber(delta, x), label=f"$\delta={delta}$", ls=style)
      >>> ax.legend(loc="upper center")
      >>> ax.set_xlabel("$x$")
      >>> ax.set_title("Huber loss function $h_{\delta}(x)$")
      >>> ax.set_xlim(-4, 4)
      >>> ax.set_ylim(0, 8)
      >>> plt.show()