まとめ- Huber 損失は誤差が小さい領域で二乗誤差(MSE)、大きい領域で絶対誤差(MAE)として振る舞う。
- 閾値パラメータ δ で切り替え点を制御し、外れ値の影響を制限しつつ微小誤差では滑らかな勾配を得る。
- scikit-learn の
HuberRegressor や XGBoost / LightGBM の objective="huber" で利用可能。
直感
#
MSE は大きな誤差を二乗で罰するので外れ値に引っ張られる。MAE は外れ値に頑健だが、原点付近で微分不可能で最適化しにくい。Huber 損失は「誤差が δ 以下なら MSE、δ を超えたら MAE」と切り替えることで、両方の長所を得る。
詳細な解説
#
数式
#
$$
L_\delta(r) = \begin{cases} \frac{1}{2} r^2 & \text{if } |r| \le \delta \\ \delta \cdot (|r| - \frac{1}{2}\delta) & \text{if } |r| > \delta \end{cases}
$$可視化
#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| import numpy as np
import matplotlib.pyplot as plt
def huber_loss(r, delta=1.0):
return np.where(np.abs(r) <= delta, 0.5 * r**2, delta * (np.abs(r) - 0.5 * delta))
r = np.linspace(-4, 4, 200)
plt.figure(figsize=(8, 4))
for d in [0.5, 1.0, 2.0]:
plt.plot(r, huber_loss(r, d), label=f"δ = {d}")
plt.plot(r, r**2, "--", label="MSE", alpha=0.5)
plt.plot(r, np.abs(r), "--", label="MAE", alpha=0.5)
plt.legend()
plt.xlabel("Residual")
plt.ylabel("Loss")
plt.title("Huber Loss vs MSE vs MAE")
plt.grid(True, alpha=0.3)
plt.show()
|
scikit-learn での利用
#
1
2
3
4
5
6
7
8
9
| from sklearn.linear_model import HuberRegressor
from sklearn.datasets import make_regression
X, y = make_regression(n_samples=200, n_features=1, noise=10, random_state=42)
y[0], y[1], y[2] = 300, -250, 400 # 外れ値を追加
huber = HuberRegressor(epsilon=1.35)
huber.fit(X, y)
print(f"Huber 係数: {huber.coef_[0]:.2f}")
|
損失関数の比較
#
| 損失 | 外れ値耐性 | 微分可能性 | 主な用途 |
|---|
| MSE | 弱い | ○(全域) | 標準的な回帰 |
| MAE | 強い | △(原点で不可) | ロバスト回帰 |
| Huber | 中間(δで制御) | ○(全域) | 外れ値がある回帰 |
| Pinball | 方向性あり | △ | 分位予測 |