母平均を推定するとき、不偏推定量である標本平均 $\bar{X}$ は「平均的に正しい」推定量です。しかし、「平均的に正しい」ことは「常に正確」であることを意味しません。もし少しだけバイアスを許容すれば、ばらつきを大幅に減らして、結果的にはもっと精度の良い推定ができるかもしれません。
実際に、ジェームズ・スタイン推定量はバイアスを持つにもかかわらず、3次元以上では不偏推定量よりも常に小さい二乗誤差を達成します。これは「少しのバイアスを代償に大幅に分散を減らす」ことの威力を示しています。
このバイアスと分散のトレードオフは、統計学と機械学習の両方で最も重要な概念の一つです。
バイアス-バリアンス分解を理解すると、以下のような場面で適切な判断ができるようになります。
- 推定量の比較: 不偏推定量とバイアスのある推定量のどちらがMSEで優れるか
- 正則化の理解: リッジ回帰やラッソが「なぜ」うまくいくか
- モデル選択: 過学習と学習不足のメカニズム
- 実験計画: 推定精度を最適化するための戦略
本記事の内容
- MSEのバイアス-バリアンス分解
- 縮小推定量のバイアス-バリアンス・トレードオフ
- リッジ回帰における実例
- 最適な縮小度の決定
- Pythonでの実装と可視化
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
- 点推定の基礎 — 不偏性・有効性・MSEの基本
- クラメール・ラオの下限 — 不偏推定量の分散の限界
- 最尤推定法の理論 — 推定量の漸近理論
バイアス-バリアンス分解の導出
MSEの分解
推定量 $\hat{\theta}$ の平均二乗誤差(MSE)は推定値と真の値の二乗差の期待値です。
$$ \text{MSE}(\hat{\theta}) = E[(\hat{\theta} – \theta)^2] $$
これをバイアスと分散に分解します。$E[\hat{\theta}]$ を加えて引くことで、
$$ \hat{\theta} – \theta = (\hat{\theta} – E[\hat{\theta}]) + (E[\hat{\theta}] – \theta) $$
右辺の第1項は推定量の平均からの偏差(ランダムな変動)、第2項はバイアス(系統的な偏り)です。二乗して期待値を取ると、
$$ E[(\hat{\theta} – \theta)^2] = E[(\hat{\theta} – E[\hat{\theta}])^2] + 2(E[\hat{\theta}] – \theta) \cdot \underbrace{E[\hat{\theta} – E[\hat{\theta}]]}_{= 0} + (E[\hat{\theta}] – \theta)^2 $$
交差項は $E[\hat{\theta} – E[\hat{\theta}]] = 0$ なので消えます。
$$ \begin{equation} \text{MSE}(\hat{\theta}) = V[\hat{\theta}] + \text{Bias}(\hat{\theta})^2 \end{equation} $$
これがバイアス-バリアンス分解です。MSEは分散とバイアスの二乗の和に分解されます。
解釈
- 分散 $V[\hat{\theta}]$: データの違いによる推定値のばらつき。サンプルの偶然性に起因する
- バイアスの二乗 $\text{Bias}^2$: 推定量の系統的な偏りの影響。推定手法の選択に起因する
不偏推定量ではバイアスがゼロなのでMSE = 分散ですが、バイアスのある推定量は分散の減少がバイアスの二乗の増加を上回れば、MSEが改善されます。
ダーツのアナロジー
ダーツで的を狙う場面を考えましょう。
- バイアス大・分散小: 毎回同じ方向にずれるが、ずれの大きさは一定。(正確ではないが精密)
- バイアス小・分散大: 平均的には的の中心を狙えているが、毎回バラバラ。(正確だが精密でない)
- バイアス小・分散小: 毎回的の中心付近に集中。(正確かつ精密 — 理想)
MSE最小化は「的からの平均二乗距離」を最小にすることに対応し、バイアスと分散のバランスが重要です。
この分解が実際にどのように機能するか、縮小推定量を通じて見ていきましょう。
縮小推定量のバイアス-バリアンス・トレードオフ
縮小推定量の一般形
標本平均 $\bar{X}$ を $\mu$ の推定量とする代わりに、定数 $c$ で縮小した $\hat{\mu}_c = c\bar{X}$ を考えます($0 < c \leq 1$)。
- $c = 1$: 不偏推定量($\hat{\mu}_1 = \bar{X}$)
- $c < 1$: 原点に向かって縮小された推定量(バイアスあり)
バイアスと分散:
$$ \text{Bias}(\hat{\mu}_c) = c\mu – \mu = (c-1)\mu $$
$$ V[\hat{\mu}_c] = c^2 \cdot \frac{\sigma^2}{n} $$
$$ \text{MSE}(\hat{\mu}_c) = c^2\frac{\sigma^2}{n} + (c-1)^2\mu^2 $$
最適な縮小度
MSEを $c$ で微分してゼロとおくと、
$$ \frac{d}{dc}\text{MSE} = 2c\frac{\sigma^2}{n} + 2(c-1)\mu^2 = 0 $$
$$ c^* = \frac{\mu^2}{\mu^2 + \sigma^2/n} = \frac{1}{1 + \sigma^2/(n\mu^2)} $$
$c^*$ は信号対雑音比 $\text{SNR} = n\mu^2/\sigma^2$ に依存します。
- SNRが大きい($\mu$ が大きいか $\sigma$ が小さい): $c^* \to 1$(ほとんど縮小しない)
- SNRが小さい($\mu$ が小さいか $\sigma$ が大きい): $c^* \to 0$(強く縮小)
$c^*$ は $\mu$ に依存するため実用上は使えませんが、データからSNRを推定して適応的に縮小度を決めるのが縮小推定の本質です。ジェームズ・スタイン推定量はまさにこのアイデアの実現です。
この理論的な枠組みがわかったところで、回帰分析におけるバイアス-バリアンス・トレードオフの実例を見ていきましょう。
リッジ回帰における実例
OLS推定量の問題
線形回帰 $\bm{y} = \bm{X}\bm{\beta} + \bm{\varepsilon}$ の最小二乗(OLS)推定量は
$$ \hat{\bm{\beta}}_{\text{OLS}} = (\bm{X}^T\bm{X})^{-1}\bm{X}^T\bm{y} $$
これは不偏推定量ですが、$\bm{X}^T\bm{X}$ の固有値が小さい(多重共線性がある)とき分散が非常に大きくなります。
リッジ回帰の推定量
リッジ回帰は $\bm{X}^T\bm{X}$ に正則化項 $\lambda\bm{I}$ を加えます。
$$ \hat{\bm{\beta}}_{\text{Ridge}} = (\bm{X}^T\bm{X} + \lambda\bm{I})^{-1}\bm{X}^T\bm{y} $$
これはバイアスを持ちます($E[\hat{\bm{\beta}}_{\text{Ridge}}] \neq \bm{\beta}$)が、分散が大幅に減少します。
バイアスと分散の表現
$\bm{X}^T\bm{X}$ の固有値分解 $\bm{X}^T\bm{X} = \bm{V}\bm{\Lambda}\bm{V}^T$ を用いると、
リッジ推定量は各固有値方向で独立に縮小されます。固有値 $d_j$ に対応する方向での縮小係数は
$$ w_j = \frac{d_j}{d_j + \lambda} $$
- $d_j \gg \lambda$: $w_j \approx 1$(ほぼ縮小しない)
- $d_j \ll \lambda$: $w_j \approx 0$(強く縮小)
小さい固有値(不安定な方向)ほど強く縮小され、大きい固有値(安定な方向)はほぼそのままです。
Pythonでリッジ回帰のバイアス-バリアンス・トレードオフを確認しましょう。
Pythonでの実装と可視化
縮小推定のバイアス-バリアンス・トレードオフ
まず、単純な縮小推定量でトレードオフを確認します。
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
mu_true = 2.0
sigma = 3.0
n = 10
c_values = np.linspace(0, 1.2, 200)
fig, axes = plt.subplots(1, 3, figsize=(16, 5))
# (a) 理論的なBias², Variance, MSE
ax = axes[0]
bias_sq = (c_values - 1)**2 * mu_true**2
variance = c_values**2 * sigma**2 / n
mse = bias_sq + variance
ax.plot(c_values, bias_sq, 'r-', linewidth=2, label='$\\mathrm{Bias}^2$')
ax.plot(c_values, variance, 'b-', linewidth=2, label='Variance')
ax.plot(c_values, mse, 'k-', linewidth=2.5, label='MSE')
c_opt = mu_true**2 / (mu_true**2 + sigma**2/n)
mse_opt = c_opt**2 * sigma**2/n + (c_opt - 1)**2 * mu_true**2
ax.plot(c_opt, mse_opt, 'k*', markersize=15)
ax.axvline(1, color='gray', linestyle=':', alpha=0.5, label='$c=1$ (unbiased)')
ax.axvline(c_opt, color='green', linestyle='--', alpha=0.7,
label=f'Optimal $c^*={c_opt:.3f}$')
ax.set_xlabel('Shrinkage factor $c$', fontsize=12)
ax.set_ylabel('Value', fontsize=12)
ax.set_title(f'Bias-Variance Tradeoff ($\\mu={mu_true}$, $\\sigma={sigma}$, n={n})', fontsize=12)
ax.legend(fontsize=8)
ax.grid(True, alpha=0.3)
# (b) SNRによるc*の変化
ax = axes[1]
snr_range = np.linspace(0.1, 20, 200)
c_opt_range = snr_range / (snr_range + 1)
mse_ratio = (c_opt_range**2 + (c_opt_range - 1)**2 * snr_range) / (1 + 0)
# MSE(c*) / MSE(c=1) = 1 / (1 + 1/SNR)
mse_improvement = 1 / (1 + 1/snr_range)
ax.plot(snr_range, c_opt_range, 'b-', linewidth=2, label='Optimal $c^*$')
ax.plot(snr_range, mse_improvement, 'r--', linewidth=2, label='MSE ratio (shrunk/unbiased)')
ax.axhline(1, color='gray', linestyle=':', alpha=0.5)
ax.set_xlabel('SNR = $n\\mu^2/\\sigma^2$', fontsize=12)
ax.set_ylabel('Value', fontsize=12)
ax.set_title('Optimal Shrinkage vs SNR', fontsize=13)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)
# (c) シミュレーション確認
ax = axes[2]
n_sim = 5000
c_test = [0.2, 0.5, c_opt, 0.9, 1.0]
for c in c_test:
estimates = [c * np.mean(np.random.normal(mu_true, sigma, n))
for _ in range(n_sim)]
mse_sim = np.mean([(e - mu_true)**2 for e in estimates])
label = f'$c={c:.2f}$, MSE={mse_sim:.3f}'
if abs(c - c_opt) < 0.01:
label = f'$c^*={c:.3f}$, MSE={mse_sim:.3f}'
ax.hist(estimates, bins=50, density=True, alpha=0.3, label=label)
ax.axvline(mu_true, color='black', linewidth=2, linestyle='--')
ax.set_xlabel('Estimate', fontsize=12)
ax.set_ylabel('Density', fontsize=12)
ax.set_title('Distribution of Shrinkage Estimators', fontsize=13)
ax.legend(fontsize=7, loc='upper left')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('bias_variance_shrinkage.png', dpi=150, bbox_inches='tight')
plt.show()
このグラフからバイアス-バリアンス・トレードオフの本質がわかります。
-
左図: $c = 1$ では分散のみ(バイアスゼロ)、$c < 1$ ではバイアスが増加し分散が減少します。MSE(黒線)は $c^* = 0.307$ で最小値を取り、不偏推定量 $c = 1$ よりも小さいMSEを実現しています。これがバイアスを許容する利点です
-
中央図: SNRが大きいほど最適な $c^*$ は1に近づき(縮小が不要)、MSE改善率も1に近づきます。SNRが小さいとき(信号が弱いとき)ほど縮小推定の効果が大きくなります
-
右図: 各縮小度での推定値の分布を比較すると、$c^*$ の分布は真の値の周辺に効率よく集中しています。$c = 0.2$ はバイアスが大きすぎ、$c = 1.0$ は分散が大きすぎるのに対し、$c^*$ がバランスの取れたトレードオフを実現しています
リッジ回帰のバイアス-バリアンス・トレードオフ
多変量の回帰問題でリッジ回帰のトレードオフを確認します。
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
# データ生成: 多重共線性のある問題
n = 50
p = 20
n_sim = 1000
# 相関のある説明変数
rho = 0.95
Sigma_x = rho * np.ones((p, p)) + (1 - rho) * np.eye(p)
L = np.linalg.cholesky(Sigma_x)
# 真の係数(疎: 最初の5個だけ非ゼロ)
beta_true = np.zeros(p)
beta_true[:5] = [3, -2, 1.5, -1, 0.5]
sigma_eps = 2.0
# 正則化パラメータの範囲
lambdas = np.logspace(-3, 4, 100)
bias_sq_all = np.zeros(len(lambdas))
variance_all = np.zeros(len(lambdas))
mse_all = np.zeros(len(lambdas))
# シミュレーション
for sim in range(n_sim):
X = np.random.standard_normal((n, p)) @ L.T
y = X @ beta_true + np.random.normal(0, sigma_eps, n)
for j, lam in enumerate(lambdas):
XtX = X.T @ X
beta_ridge = np.linalg.solve(XtX + lam * np.eye(p), X.T @ y)
mse_all[j] += np.sum((beta_ridge - beta_true)**2) / n_sim
# 理論的なバイアスと分散の計算(1つのXの実現値に基づく近似)
X_fixed = np.random.standard_normal((n, p)) @ L.T
XtX_fixed = X_fixed.T @ X_fixed
for j, lam in enumerate(lambdas):
W = np.linalg.inv(XtX_fixed + lam * np.eye(p)) @ XtX_fixed
bias = (W - np.eye(p)) @ beta_true
bias_sq_all[j] = np.sum(bias**2)
# 分散の近似
cov_beta = sigma_eps**2 * np.linalg.inv(XtX_fixed + lam * np.eye(p)) @ XtX_fixed @ np.linalg.inv(XtX_fixed + lam * np.eye(p))
variance_all[j] = np.trace(cov_beta)
fig, axes = plt.subplots(1, 2, figsize=(14, 5.5))
# (a) Bias², Variance, MSE vs λ
ax = axes[0]
ax.semilogx(lambdas, bias_sq_all, 'r-', linewidth=2, label='$\\mathrm{Bias}^2$')
ax.semilogx(lambdas, variance_all, 'b-', linewidth=2, label='Variance')
ax.semilogx(lambdas, mse_all, 'k-', linewidth=2.5, label='MSE (simulated)')
ax.semilogx(lambdas, bias_sq_all + variance_all, 'k--', linewidth=1.5, alpha=0.5,
label='$\\mathrm{Bias}^2$ + Variance')
opt_idx = np.argmin(mse_all)
ax.axvline(lambdas[opt_idx], color='green', linestyle='--', alpha=0.7,
label=f'Optimal $\\lambda = {lambdas[opt_idx]:.2f}$')
ax.plot(lambdas[opt_idx], mse_all[opt_idx], 'g*', markersize=15)
ax.set_xlabel('$\\lambda$ (regularization parameter)', fontsize=12)
ax.set_ylabel('Value', fontsize=12)
ax.set_title('Ridge Regression: Bias-Variance Tradeoff', fontsize=13)
ax.legend(fontsize=8)
ax.grid(True, alpha=0.3)
# (b) 係数の縮小パス
ax = axes[1]
coef_paths = np.zeros((len(lambdas), p))
X_fixed2 = np.random.standard_normal((n, p)) @ L.T
y_fixed = X_fixed2 @ beta_true + np.random.normal(0, sigma_eps, n)
XtX2 = X_fixed2.T @ X_fixed2
for j, lam in enumerate(lambdas):
coef_paths[j] = np.linalg.solve(XtX2 + lam * np.eye(p), X_fixed2.T @ y_fixed)
for k in range(min(p, 8)):
ax.semilogx(lambdas, coef_paths[:, k], linewidth=1.5, alpha=0.7,
label=f'$\\beta_{{{k+1}}}$ (true={beta_true[k]:.1f})')
ax.axvline(lambdas[opt_idx], color='green', linestyle='--', alpha=0.5)
ax.set_xlabel('$\\lambda$', fontsize=12)
ax.set_ylabel('$\\hat{\\beta}$', fontsize=12)
ax.set_title('Coefficient Shrinkage Path', fontsize=13)
ax.legend(fontsize=7, loc='upper right', ncol=2)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('ridge_bias_variance.png', dpi=150, bbox_inches='tight')
plt.show()
このグラフからリッジ回帰のバイアス-バリアンス・トレードオフが確認できます。
-
左図: $\lambda = 0$(OLS)では分散が最大でバイアスはゼロ。$\lambda$ を増やすとバイアスの二乗が増加し分散が減少します。MSEは最適な $\lambda$ で最小値を取り、OLSより改善されています。特に多重共線性($\rho = 0.95$)の強い問題では分散の削減効果が大きいです
-
右図: 係数の推定値が $\lambda$ の増加とともに0に向かって縮小する「シュリンケージ・パス」です。非ゼロの真の係数($\beta_1 = 3, \beta_2 = -2$ など)は $\lambda$ が小さいときに良く推定されますが、$\lambda$ が大きすぎると0に潰されてバイアスが生じます
まとめ
本記事では、バイアス-バリアンス分解の理論と実例を解説しました。
- MSE = 分散 + バイアスの二乗 という分解が推定量の総合的な評価基準を与える
- 不偏推定量はバイアスゼロだが、バイアスを少し許容することで分散を大幅に減少させ、MSEを改善できる場合がある
- 縮小推定の最適度は信号対雑音比(SNR)に依存し、SNRが小さいほど縮小の効果が大きい
- リッジ回帰は多重共線性のある問題で分散を劇的に減らし、最適な $\lambda$ でMSEを最小化する
- バイアス-バリアンス・トレードオフは機械学習の正則化・モデル選択の理論的基礎でもある
次のステップとして、以下の記事も参考にしてください。
- ベイズ統計 vs 頻度主義 — 2つのアプローチの本質的な違い
- クラメール・ラオの下限 — 不偏推定量の分散の理論的限界
- 経験ベイズ法 — 縮小推定の発展形