推定量にバイアス(偏り)があるとき、それを補正するにはどうすればよいだろうか? 理論的にバイアスを計算できれば話は簡単だが、複雑な推定量ではそれが困難なことも多い。
ジャックナイフ法(jackknife method)は、手元のデータを「再利用」してバイアスを推定・補正する手法である。名前の由来は、アメリカの折り畳みナイフ「ジャックナイフ」で、データから1つずつ「切り取る」操作にちなんでいる。1949年にMaurice Quenouilleが提案・1956年に改良し、1958年にJohn Tukeyが拡張して「jackknife」と命名した。
ジャックナイフ法はリサンプリング法(resampling method)の一種である。元のデータから部分標本を作り、統計量の性質を調べる手法の総称だ。ブートストラップ法と並んで、現代統計学で広く使われている。
本記事では、ジャックナイフ法によるバイアス補正の仕組みと、具体的な計算方法を解説する。
基本的なアイデア
標本 X_1, X_2, \ldots, X_n から計算した推定量 \hat{\theta} を考える。この推定量にバイアス b(\theta) = E[\hat{\theta}] - \theta があるとき、それを推定して補正したい。
ジャックナイフ法の発想は単純である。i 番目のデータ X_i を除いた n-1 個の部分標本から、同じ推定量を計算する。これを全ての i について行い、元の推定量と比較することで、バイアスを推定できる。
ジャックナイフ法では、データを1つずつ除いた n 個の部分標本を作る。これを「leave-one-out」と呼ぶ。各部分標本のサイズは n-1 である。
ジャックナイフ推定量の定義
標本 X_1, \ldots, X_n に基づく推定量を \hat{\theta} とする。i 番目のデータを除いた部分標本から計算した推定量を \hat{\theta}_{(i)} と書く。
これら n 個の推定量の平均を
と定義する。このとき、ジャックナイフバイアス推定量は
と定義される。これを用いて、バイアスを補正したジャックナイフ推定量は
となる。2番目の等式は展開すればすぐに確認できる。
なぜ (n−1) をかけるのか
バイアス推定量に (n-1) をかける理由を説明しよう。バイアスが \dfrac{1}{n} のオーダーで
と書けると仮定する(多くの推定量でこの形が成り立つ)。このとき、サイズ n-1 の部分標本から計算した \hat{\theta}_{(i)} については
となる。したがって、平均 \hat{\theta}_{(\cdot)} の期待値は
ここで \hat{\theta}_{(\cdot)} - \hat{\theta} の期待値を計算すると
よって
これは元のバイアス \dfrac{b(\theta)}{n} と一致する。つまり、(n-1) をかけることで、バイアスの不偏推定量が得られるのである。
計算例1:μ² の推定
母平均 \mu の2乗 \mu^2 を、標本平均の2乗 \hat{\theta} = \bar{X}^2 で推定する場合を考える。
E[\bar{X}^2] = \mu^2 + \dfrac{\sigma^2}{n} なので、この推定量には \dfrac{\sigma^2}{n} のバイアスがある。ジャックナイフ法でこれを補正してみよう。
データ
5個のデータ x_1, x_2, x_3, x_4, x_5 = 3.2, 4.1, 3.8, 4.5, 3.9 が得られたとする。
Step 1: 元の推定量を計算
標本平均は \bar{x} = \dfrac{3.2 + 4.1 + 3.8 + 4.5 + 3.9}{5} = 3.9 なので
Step 2: Leave-one-out 推定量を計算
各データを1つずつ除いて、残り4つの平均の2乗を計算する。
Step 3: 平均を計算
Step 4: ジャックナイフ推定量を計算
理論値との比較
理論的なバイアス補正は \bar{x}^2 - \dfrac{s^2}{n} で与えられる。不偏分散 s^2 = 0.225 を使うと
ジャックナイフ推定量と一致した。実は、\bar{X}^2 の場合、ジャックナイフ法と理論的バイアス補正は常に一致することが示される。
計算例2:標本分散のバイアス補正
標本分散 \hat{\theta} = \dfrac{1}{n}\sum_{i=1}^{n}(X_i - \bar{X})^2(n で割る方)のバイアスをジャックナイフ法で補正する。
データ
5人のテスト得点 72, 68, 85, 79, 76 を使う。
計算
標本平均は \bar{x} = 76、標本分散(n で割る)は
各 leave-one-out 推定量を計算すると
平均は \hat{\theta}_{(\cdot)} = 31.875。ジャックナイフ推定量は
これは不偏分散 \dfrac{1}{n-1}\sum_{i=1}^{n}(X_i - \bar{X})^2 = \dfrac{170}{4} = 42.5 と一致する。ジャックナイフ法により、標本分散のバイアスが補正され、不偏分散が得られた。
標準誤差の推定
ジャックナイフ法は、バイアス補正だけでなく標準誤差の推定にも使える。推定量 \hat{\theta} の標準誤差は
で推定できる。係数 \dfrac{n-1}{n} は、leave-one-out 推定量間の相関を補正するためのものである。
適用上の注意
ジャックナイフ法は全ての推定量に有効とは限らない。特に、中央値や分位点のように不連続な推定量に対しては、性能が悪いことが知られている。そのような場合は、ブートストラップ法がより適切である。
また、バイアスが \dfrac{1}{n} より高次のオーダー(例えば \dfrac{1}{n^2})で存在する場合、ジャックナイフ法では完全に補正できない。ただし、通常の推定量では \dfrac{1}{n} オーダーのバイアスが主要項なので、実用上は問題になりにくい。
練習問題
標本平均 \bar{x} = 4、標本分散 \hat{\theta} = \dfrac{(2-4)^2 + (5-4)^2 + (3-4)^2 + (6-4)^2}{4} = \dfrac{10}{4} = 2.5
各 leave-one-out 推定量:
\hat{\theta}_{(\cdot)} = \dfrac{1}{4}\left(\dfrac{14}{9} + \dfrac{26}{9} + \dfrac{14}{9} + \dfrac{14}{9}\right) = \dfrac{68}{36} = \dfrac{17}{9}
ジャックナイフ推定量:
不偏分散 s^2 = \dfrac{10}{3} \approx 3.333 と一致する。
E[\hat{\theta}] = \theta + \dfrac{b(\theta)}{n}、E[\hat{\theta}_{(i)}] = \theta + \dfrac{b(\theta)}{n-1} より
よって E[\hat{\theta}_{\text{jack}}] = \theta となり、バイアスは0である。
まとめ
| 項目 | 内容 |
|---|---|
| Leave-one-out 推定量 | \hat{\theta}_{(i)}:i 番目のデータを除いた推定量 |
| 平均 | \hat{\theta}_{(\cdot)} = \dfrac{1}{n}\sum_{i=1}^{n} \hat{\theta}_{(i)} |
| バイアス推定 | \widehat{\text{bias}} = (n-1)(\hat{\theta}_{(\cdot)} - \hat{\theta}) |
| ジャックナイフ推定量 | \hat{\theta}_{\text{jack}} = n\hat{\theta} - (n-1)\hat{\theta}_{(\cdot)} |
| 標準誤差 | \widehat{\text{se}} = \sqrt{\dfrac{n-1}{n}\sum_{i=1}^{n}(\hat{\theta}_{(i)} - \hat{\theta}_{(\cdot)})^2} |
| 適用 | バイアスが O(1/n) の推定量に有効 |
Pythonで計算する
ジャックナイフ法によるバイアス補正と標準誤差推定を実装する。
import numpy as np
def jackknife(data, estimator):
"""
ジャックナイフ法によるバイアス補正と標準誤差推定
Parameters:
-----------
data : array-like
データ
estimator : callable
推定量を計算する関数
Returns:
--------
dict : ジャックナイフ推定量、バイアス推定、標準誤差
"""
data = np.array(data)
n = len(data)
# 元の推定量
theta_hat = estimator(data)
# Leave-one-out 推定量
theta_i = np.array([
estimator(np.delete(data, i, axis=0)) for i in range(n)
])
theta_dot = np.mean(theta_i)
# バイアス推定
bias = (n - 1) * (theta_dot - theta_hat)
# ジャックナイフ推定量
theta_jack = n * theta_hat - (n - 1) * theta_dot
# 標準誤差
se = np.sqrt((n - 1) / n * np.sum((theta_i - theta_dot)**2))
return {
'original': theta_hat,
'jackknife': theta_jack,
'bias': bias,
'se': se,
'leave_one_out': theta_i
}
# ===== 例1: μ² の推定 =====
print("=== μ² の推定(標本平均の2乗) ===")
data1 = np.array([3.2, 4.1, 3.8, 4.5, 3.9])
def mean_squared(x):
return np.mean(x)**2
result1 = jackknife(data1, mean_squared)
print(f"データ: {data1}")
print(f"元の推定量 θ̂ = X̄² = {result1['original']:.4f}")
print(f"Leave-one-out 推定量: {result1['leave_one_out']}")
print(f"バイアス推定: {result1['bias']:.4f}")
print(f"ジャックナイフ推定量: {result1['jackknife']:.4f}")
print(f"標準誤差: {result1['se']:.4f}")
# 理論値との比較
s2 = np.var(data1, ddof=1)
theoretical = np.mean(data1)**2 - s2/len(data1)
print(f"理論的バイアス補正: {theoretical:.4f}")
print()
# ===== 例2: 標本分散のバイアス補正 =====
print("=== 標本分散のバイアス補正 ===")
data2 = np.array([72, 68, 85, 79, 76])
def biased_var(x):
return np.var(x, ddof=0) # n で割る
result2 = jackknife(data2, biased_var)
print(f"データ: {data2}")
print(f"標本分散(n で割る): {result2['original']:.4f}")
print(f"ジャックナイフ推定量: {result2['jackknife']:.4f}")
print(f"不偏分散(n-1 で割る): {np.var(data2, ddof=1):.4f}")
print()
# ===== 例3: 相関係数の標準誤差 =====
print("=== 相関係数の標準誤差推定 ===")
np.random.seed(42)
x = np.array([1.2, 2.5, 3.1, 4.0, 5.2, 6.1, 7.0, 8.3])
y = 2 * x + np.random.normal(0, 1, len(x))
def correlation(data):
# data は (x, y) のペアを想定
return np.corrcoef(data[:, 0], data[:, 1])[0, 1]
xy_data = np.column_stack([x, y])
result3 = jackknife(xy_data, correlation)
print(f"相関係数: {result3['original']:.4f}")
print(f"ジャックナイフ標準誤差: {result3['se']:.4f}")