scipy.special.pseudo_huber#

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

伪 Huber 损失函数。

\[\mathrm{pseudo\_huber}(\delta, r) = \delta^2 \left( \sqrt{ 1 + \left( \frac{r}{\delta} \right)^2 } - 1 \right)\]
参数:
delta类数组

输入数组,表明柔性二次与线性损失变化点。

r类数组

输入数组,可能表示残差。

outndarray,可选

函数结果的可选输出数组

返回:
res标量或 ndarray

计算出的伪 Huber 损失函数值。

参见

huber

此函数近似执行的类似函数

说明

huber 类似,pseudo_huber 通常在统计信息或机器学习中充当稳健的损失函数,以减少异常值的影响。与 huber 不同的是,pseudo_huber 是平滑的。

通常,r 表示残差,这是模型预测值和数据值之间的差值。然后,对于 \(|r|\leq\delta\)pseudo_huber 类似于平方误差,而对于 \(|r|>\delta\),它类似于绝对误差。这样,Pseudo-Huber 损失函数通常在针对较小的残差进行模型拟合时可以快速收敛,这类似于平方误差损失函数,但仍然可以降低异常值(\(|r|>\delta\))的影响,这类似于绝对误差损失函数。由于 \(\delta\) 是平方误差方案和绝对误差方案之间的临界点,因此针对每个问题都需要对其进行仔细调整。 pseudo_huber 也是凸函数,使其适用于基于梯度的优化。 [1] [2]

已添加到 0.15.0 版中。

参考

[1]

Hartley、Zisserman,“计算机视觉中的多视角几何”。2003 年。剑桥大学出版社,第 619 页

[2]

Charbonnier 等。“计算成像中的确定性保边正则化”。1997 年。IEEE 图像处理事务。6 (2):298 - 311。

示例

导入所有必要的模块。

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

计算 delta=1 时在 r=2 处的该函数。

>>> pseudo_huber(1., 2.)
1.2360679774997898

通过为 delta 提供列表或 NumPy 数组来计算 delta 不同的 r=2 处的函数。

>>> pseudo_huber([1., 2., 4.], 3.)
array([2.16227766, 3.21110255, 4.        ])

通过为 r 提供列表或 NumPy 数组来计算 delta=1 时函数在多个点处的函数。

>>> pseudo_huber(2., np.array([1., 1.5, 3., 4.]))
array([0.47213595, 1.        , 3.21110255, 4.94427191])

通过为这两个参数同时提供具有兼容形状的数组进行广播,可以针对不同的 deltar 计算函数。

>>> r = np.array([1., 2.5, 8., 10.])
>>> deltas = np.array([[1.], [5.], [9.]])
>>> print(r.shape, deltas.shape)
(4,) (3, 1)
>>> pseudo_huber(deltas, r)
array([[ 0.41421356,  1.6925824 ,  7.06225775,  9.04987562],
       [ 0.49509757,  2.95084972, 22.16990566, 30.90169944],
       [ 0.49846624,  3.06693762, 27.37435121, 40.08261642]])

针对不同的 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, pseudo_huber(delta, x), label=rf"$\delta={delta}$",
...             ls=style)
>>> ax.legend(loc="upper center")
>>> ax.set_xlabel("$x$")
>>> ax.set_title(r"Pseudo-Huber loss function $h_{\delta}(x)$")
>>> ax.set_xlim(-4, 4)
>>> ax.set_ylim(0, 8)
>>> plt.show()
../../_images/scipy-special-pseudo_huber-1_00_00.png

最后,通过绘制 huber 和 pseudo_huber 相对于 r 的梯度图来说明二者的区别。该图表明 pseudo_huber 是连续可微的,而 huber 在点 ±δ 处不是。

>>> def huber_grad(delta, x):
...     grad = np.copy(x)
...     linear_area = np.argwhere(np.abs(x) > delta)
...     grad[linear_area]=delta*np.sign(x[linear_area])
...     return grad
>>> def pseudo_huber_grad(delta, x):
...     return x* (1+(x/delta)**2)**(-0.5)
>>> x=np.linspace(-3, 3, 500)
>>> delta = 1.
>>> fig, ax = plt.subplots(figsize=(7, 7))
>>> ax.plot(x, huber(delta, x), label="Huber", ls="dashed")
>>> ax.plot(x, huber_grad(delta, x), label="Huber Gradient", ls="dashdot")
>>> ax.plot(x, pseudo_huber(delta, x), label="Pseudo-Huber", ls="dotted")
>>> ax.plot(x, pseudo_huber_grad(delta, x), label="Pseudo-Huber Gradient",
...         ls="solid")
>>> ax.legend(loc="upper center")
>>> plt.show()
../../_images/scipy-special-pseudo_huber-1_01_00.png