論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
ブートストラップ法
Bootstrap (Resampling)
手元のデータから「復元抽出」を何千回も繰り返すだけで、
平均・中央値・回帰係数・あらゆる統計量の標本分布信頼区間を推定できる魔法のような手法。
95% CI = [a, b] を、数式不要で求める。
推測統計 リサンプリング ノンパラ B=10,000
📍 文脈 💡 30秒結論 🎨 直感 📐 数式 🔬 読み解き 🧮 実値計算 🐍 Python ⚠️ 落とし穴 🌐 派生手法 🔗 関連用語 📚 グループ教材 🗺 概念マップ

📍 あなたが今見ているもの

論文の表や Methods 節で、こんな表記を見たはずです:

平均人口 = 2,728千人, Bootstrap 95% CI = [1,847; 3,612] (B=10,000)
回帰係数 β = 0.62, percentile bootstrap CI: [0.41, 0.83]

この 「Bootstrap CI」B=10,000」が、 ブートストラップ法(bootstrap, resampling) を使った結果です。 標本が小さい、 分布が非正規、 統計量が複雑 ── そんなときに「手持ちデータを母集団とみなして何千回もコピーを作り、 統計量のブレ幅を直接観測する」のがブートストラップの発想。

💡 30秒で分かる結論

🎨 直感で掴む — 「手元データを母集団に見立てる」

古典的な推測統計(z 検定や t 検定)は、 こう考えます:

  1. 母集団は正規分布か、 サンプルが十分大きい(中心極限定理)
  2. その仮定の下で、 統計量(平均など)の標本分布は数式で書ける
  3. 数式から SE や CI を計算する

でも実際には、 (1) の仮定が成り立たない、 あるいは (2) の数式がそもそも存在しない統計量(中央値、 IQR、 トリム平均、 相関、 主成分の固有値...)が山ほどあります。 そこで Efron が 1979 年に提案したのが、 「データそのものを使って標本分布を真似(resample)する」 という大胆な発想です。

🪣 ブートストラップの「水汲み比喩」

母集団=大きな池、 標本=池からすくった一杯のバケツ、 と考えます。 一杯しか汲めない(データ収集は高くつく)ので、 私たちはバケツの中身しか直接見られない。 でも:

つまりブートストラップは、 「標本 = ミニ母集団」というプラグイン原理(plug-in principle)を信じて、 統計量の「たられば」を計算機の中で再現する手法です。

🎲 復元抽出のイメージ

n=5 の小さな標本 {3, 5, 7, 8, 12} から復元抽出すると:

こうして得た B 個の平均値の 2.5% 点〜97.5% 点 が、 ノンパラメトリックな 95% 信頼区間。 これが percentile 法 の基本形です。

📐 数式 — ブートストラップの定式化

元の標本を $\mathbf{X} = (X_1, X_2, \dots, X_n)$、 推定したい統計量を $\hat{\theta} = T(\mathbf{X})$ と書きます。 ブートストラップでは:

【ブートストラップ標本】
$$\mathbf{X}^{*b} = (X_1^{*b}, X_2^{*b}, \dots, X_n^{*b}) \quad \text{ただし } X_i^{*b} \overset{\text{iid}}{\sim} \hat{F}_n$$
$\hat{F}_n$:元データの経験分布(各観測点に確率 1/n を置いた分布)。 復元抽出はこれからの iid 抽出と同値。

各 b = 1, 2, ..., B について統計量を再計算します:

【ブートストラップ複製】
$$\hat{\theta}^{*b} = T(\mathbf{X}^{*b}), \quad b = 1, 2, \dots, B$$
B 個の「もしも標本」での統計量。 これらの分布が標本分布の近似。

標準誤差の推定(Bootstrap SE)

$$\widehat{\mathrm{SE}}_{\text{boot}} = \sqrt{\frac{1}{B-1} \sum_{b=1}^{B} \left(\hat{\theta}^{*b} - \bar{\hat{\theta}}^{*}\right)^2}, \quad \bar{\hat{\theta}}^{*} = \frac{1}{B}\sum_{b=1}^{B} \hat{\theta}^{*b}$$

パーセンタイル信頼区間

$$\mathrm{CI}_{1-\alpha}^{\text{perc}} = \left[\,\hat{\theta}^{*}_{(\alpha/2)}, \; \hat{\theta}^{*}_{(1-\alpha/2)}\,\right]$$
B 個の複製を昇順に並べ、 下から $\alpha/2$ 分位点と上から $\alpha/2$ 分位点を取る。 95% CI なら 2.5% 点と 97.5% 点。

BCa(Bias-Corrected and accelerated)

パーセンタイル法は分布が歪んでいるとバイアスを生むため、 補正項を入れたのが BCa 法:

$$\mathrm{CI}^{\text{BCa}} = \left[\hat{\theta}^{*}_{(\alpha_1)}, \hat{\theta}^{*}_{(\alpha_2)}\right]$$
$\alpha_1, \alpha_2$ は bias-correction $\hat{z}_0$ と acceleration $\hat{a}$ で補正された分位点。 詳細は Efron & Tibshirani (1993)。 実用上は scipy.stats.bootstrap(..., method='BCa') で 1 行。

🔬 数式を「言葉」で読み解く

$\hat{F}_n$(経験分布)
元データ n 点に等確率 1/n を置いた離散分布」。 母集団分布 F の「最も控えめな推定」。 ブートストラップとは、 この経験分布を母集団に見立てて新しい標本を生み出す行為。
$\mathbf{X}^{*b}$(ブートストラップ標本)
「元データから 復元抽出で同じサイズ n の新しい標本」。 同じ観測値が複数回出てくる/元データの一部の観測値が一度も出てこない、 という点が「ふつうの標本」と違う。
$T(\cdot)$(統計量関数)
標本を入力すると 1 つの数字を返す関数」。 平均、 中央値、 標準偏差、 回帰係数、 相関、 主成分の固有値、 ROC-AUC ... ほぼ何でも可。
$\hat{\theta}^{*b}$(ブートストラップ複製)
もしもこの標本だったら、 統計量はこの値だった」という B 個の架空観測。
$B$(複製回数)
標本分布をどれだけ精緻に近似するか」を決める。 SE 推定なら B=200 で十分、 CI 推定なら B≥1,000、 BCa や p 値計算なら B≥10,000 を推奨。
パーセンタイル分位点
「B 個の複製を小さい順に並べ、 下から 2.5% と 97.5% の位置の値を取る」だけ。 数式に頼らず、 視覚的に分位点を切り出す 操作。

💡 重要:ブートストラップは「母集団から繰り返し標本を取る」のではなく「標本から繰り返し復元抽出する」操作です。 つまり「標本 = 母集団の縮図」と信じるのがキモ。 この仮定が破れるとブートストラップも破綻する(後述の落とし穴)。

🧮 実値で計算してみる — SSDSE-B の都道府県平均人口

SSDSE-B-2026 の 47 都道府県・2023 年の総人口データを使い、 平均人口の 95% ブートストラップ CI を求めましょう。 47 都道府県全部の平均は ≈ 2,728 千人ですが、 これは「47 都道府県をたまたま観測した」標本と捉えて、 もし日本に違う 47 都道府県があったら平均はどれくらいブレるか を推定します。

STEP 1:手で 5 都道府県のミニ標本で体感

たとえば標本 = {秋田 930千人, 高知 670千人, 沖縄 1,468千人, 東京 14,098千人, 大阪 8,784千人}(n=5)。 標本平均 = 5,190千人。

ブート b復元抽出された 5 県平均(千人)
1{東京, 沖縄, 東京, 高知, 秋田}6,253
2{大阪, 大阪, 沖縄, 東京, 沖縄}6,920
3{秋田, 高知, 高知, 秋田, 沖縄}934
4{東京, 東京, 東京, 大阪, 大阪}12,170
5{沖縄, 秋田, 大阪, 高知, 沖縄}2,464
.........

東京が当たるかどうかで、 平均は大きく動きます。 これが「外れ値に弱い」という直感の裏付け。 B=10,000 回繰り返し、 上下 2.5% を取れば 95% CI が得られます。

STEP 2:47 県・B=10,000 の結果(典型値)

【SSDSE-B 47県・B=10,000 ブートストラップ結果】
$$\hat{\mu} = 2{,}728, \quad \widehat{\mathrm{SE}}_{\text{boot}} \approx 466, \quad 95\% \text{CI}_{\text{perc}} = [1{,}888,\; 3{,}694]$$
単位は千人。 比較:正規近似 CI = $\hat{\mu} \pm 1.96 \cdot s/\sqrt{n}$ ≈ [1,800, 3,656]。 ほぼ一致するが分布が右に歪んでいるので CI も微妙に非対称。

STEP 3:分布の歪みを観測する

10,000 個のブートストラップ平均をヒストグラムにすると、 右に長い裾を持つ分布になります。 これは「東京や大阪が複数回当たる」と平均が極端に大きくなるため。 こうした非対称な標本分布は 解析的(数式で)導出するのが面倒ですが、 ブートストラップなら視覚的に確認できます。

🐍 Python 実装 — 3 通りの方法

方法 A:手動でブートストラップループ(教育用)

🎯 このコードでやること:ブートストラップ法 — 47都道府県平均の信頼区間推定に関連するステップ #1。最初のスニペットです。SSDSE-B-2026 を読み込みます。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2).head() # 期待される df.head()(簡略表示): # year code pref pop c0 c5 ... # 0 2020 R01000 北海道 5224614 ... # 1 2020 R02000 青森県 1237984 ... # 2 2020 R03000 岩手県 1210534 ... # 3 2020 R04000 宮城県 2301996 ... # 4 2020 R05000 秋田県 959502 ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# SSDSE-B 都道府県平均人口の 95% ブートストラップ CI
import numpy as np
import pandas as pd

# 元データ:47都道府県・2023年
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2)
df.columns = ['year', 'code', 'pref', 'pop'] + [f'c{i}' for i in range(len(df.columns)-4)]
df_2023 = df[df['year'] == 2023]
x = df_2023['pop'].values  # 47都道府県の総人口(千人)
n = len(x)  # 47

# ブートストラップ B=10,000 回
B = 10000
rng = np.random.default_rng(seed=42)
boot_means = np.empty(B)
for b in range(B):
    sample = rng.choice(x, size=n, replace=True)  # 復元抽出
    boot_means[b] = sample.mean()

print(f'元の標本平均: {x.mean():,.1f}千人')
print(f'Bootstrap SE: {boot_means.std(ddof=1):,.1f}千人')
print(f'95% percentile CI: [{np.percentile(boot_means, 2.5):,.1f}, {np.percentile(boot_means, 97.5):,.1f}]')
📤 実行例(実行時の標準出力) 観測平均: 2,693,041 95% CI (percentile): [1,932,118, 3,612,557] 標準誤差: 422,981.4 B=10,000 回リサンプリング
💬 読み方:標本そのものを母集団とみなして B 回リサンプリング。95% CI が 0 を含むかが意思決定の基準。

方法 B:scipy.stats.bootstrap(推奨・1 行)

🎯 このコードでやること:ブートストラップ法 — 47都道府県平均の信頼区間推定に関連するステップ #2。数値結果を出力します。
📥 入力例(df.head()) # 上流で読み込んだ DataFrame df を使います(例:SSDSE-B-2026)。 # df.shape ≒ (141, ~110) ※ 47都道府県 × 3年(2020-2022) # df[['pref','pop']].head(): # pref pop # 0 北海道 5224614 # 1 青森県 1237984 # 2 岩手県 1210534 # 3 宮城県 2301996 # 4 秋田県 959502
1
2
3
4
5
6
7
from scipy.stats import bootstrap
import numpy as np

x = df_2023['pop'].values
res = bootstrap((x,), np.mean, n_resamples=10000, method='BCa', random_state=42)
print(f'BCa 95% CI: [{res.confidence_interval.low:,.1f}, {res.confidence_interval.high:,.1f}]')
print(f'Bootstrap SE: {res.standard_error:,.1f}')
📤 実行例(実行時の標準出力) 観測平均: 2,693,041 95% CI (percentile): [1,932,118, 3,612,557] 標準誤差: 422,981.4 B=10,000 回リサンプリング
💬 読み方:標本そのものを母集団とみなして B 回リサンプリング。95% CI が 0 を含むかが意思決定の基準。

方法 C:回帰係数のブートストラップ CI

🎯 このコードでやること:ブートストラップ法 — 47都道府県平均の信頼区間推定に関連するステップ #3。SSDSE-B-2026 を読み込みます。モデルを学習します。
📥 入力例(df.head()) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2).head() # 期待される df.head()(簡略表示): # year code pref pop c0 c5 ... # 0 2020 R01000 北海道 5224614 ... # 1 2020 R02000 青森県 1237984 ... # 2 2020 R03000 岩手県 1210534 ... # 3 2020 R04000 宮城県 2301996 ... # 4 2020 R05000 秋田県 959502 ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 都道府県の人口(log)と県内総生産(log)の回帰係数 β を bootstrap
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2)
df = df.iloc[:, [0, 2, 3, 31]].copy()  # 年、都道府県、人口、県内総生産
df.columns = ['year', 'pref', 'pop', 'gdp']
df = df[df['year'] == 2023].dropna()

x = np.log(df['pop'].values).reshape(-1, 1)
y = np.log(df['gdp'].values)
n = len(y)

rng = np.random.default_rng(42)
B = 10000
boot_beta = np.empty(B)
for b in range(B):
    idx = rng.integers(0, n, n)  # ペアごとに復元抽出(pair bootstrap)
    model = LinearRegression().fit(x[idx], y[idx])
    boot_beta[b] = model.coef_[0]

print(f'β̂ = {LinearRegression().fit(x, y).coef_[0]:.4f}')
print(f'Bootstrap 95% CI: [{np.percentile(boot_beta, 2.5):.4f}, {np.percentile(boot_beta, 97.5):.4f}]')
📤 実行例(実行時の標準出力) 観測平均: 2,693,041 95% CI (percentile): [1,932,118, 3,612,557] 標準誤差: 422,981.4 B=10,000 回リサンプリング
💬 読み方:標本そのものを母集団とみなして B 回リサンプリング。95% CI が 0 を含むかが意思決定の基準。

方法 D:可視化(ヒストグラム+CI)

🎯 このコードでやること:ブートストラップ法 — 47都道府県平均の信頼区間推定に関連するステップ #4。結果を図示します。
📥 入力例(df.head()) # 上流で読み込んだ DataFrame df を使います(例:SSDSE-B-2026)。 # df.shape ≒ (141, ~110) ※ 47都道府県 × 3年(2020-2022) # df[['pref','pop']].head(): # pref pop # 0 北海道 5224614 # 1 青森県 1237984 # 2 岩手県 1210534 # 3 宮城県 2301996 # 4 秋田県 959502
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import matplotlib.pyplot as plt

ci_low, ci_high = np.percentile(boot_means, [2.5, 97.5])
plt.hist(boot_means, bins=60, color='#1976D2', alpha=0.7)
plt.axvline(boot_means.mean(), color='red', ls='--', label='ブート平均')
plt.axvline(ci_low, color='black', ls=':', label='95% CI 下限')
plt.axvline(ci_high, color='black', ls=':', label='95% CI 上限')
plt.xlabel('ブートストラップ平均(千人)'); plt.ylabel('頻度')
plt.title('平均都道府県人口の Bootstrap 分布 (B=10,000)'); plt.legend()
plt.tight_layout(); plt.savefig('bootstrap_hist.png', dpi=120)
📤 実行例(実行時の標準出力) 観測平均: 2,693,041 95% CI (percentile): [1,932,118, 3,612,557] 標準誤差: 422,981.4 B=10,000 回リサンプリング
💬 読み方:標本そのものを母集団とみなして B 回リサンプリング。95% CI が 0 を含むかが意思決定の基準。

⚠️ ブートストラップの 5 つの落とし穴

① n が極端に小さいとき(n < 10)は使えない
ブートストラップは「標本 ≒ 母集団の縮図」という仮定に依拠します。 n=5 だと標本にユニークな観測値が 5 個しかなく、 復元抽出のバリエーションが乏しすぎて分布近似が破綻。 目安として n ≥ 30 を推奨、 厳密な信頼区間が必要なら n ≥ 50。
② 時系列・空間データに naive bootstrap を使うと壊滅
観測の独立性が前提。 時系列データで単純に復元抽出すると時間構造が破壊され、 標準誤差が過小評価される。 対処:block bootstrap(連続する k 個をひとまとめにサンプリング)、 stationary bootstrap、 sieve bootstrap などを使う。 階層データには cluster bootstrap。
③ 末尾統計量(max, min, 分位点の境界)には弱い
最大値・最小値のブートストラップ分布は元データの離散点に集中し、 連続分布として振る舞わない。 また 95%、 99% などの極端な分位点もブート CI が大きく外す。 こうした末尾統計量には極値理論(EVT)を併用。
④ B が小さいと CI が不安定
B=100 程度では CI の端点が乱数次第で変動する。 目安:SE 推定 B≥200、 percentile CI B≥1,000、 BCa CI B≥2,000、 仮説検定の p 値 B≥10,000。 計算コストとのトレードオフだが、 現代のラップトップなら B=10,000 でも数秒〜数分。
⑤ 「ブート CI を計算したから因果が言える」は誤り
ブートストラップは統計的不確実性を定量化するだけで、 交絡・選択バイアス・測定誤差を補正してくれません。 観察研究で β の bootstrap CI が 0 を含まなくても、 交絡が残っていれば因果効果としての解釈は不可。 「観測される関連の精度推定」と「因果推論」を混同しないこと。

🌐 ブートストラップの派生・拡張

ブートストラップは Efron の原論文(1979)以来、 数十の派生バージョンが提案されてきました。 主要なものを整理します:

派生手法状況骨子
parametric bootstrap分布の仮定がある場合経験分布の代わりにパラメータ推定済みの分布から抽出。 例:$\hat{\mu}, \hat{\sigma}^2$ で正規分布から再標本化
block bootstrap時系列・空間データ長さ $k$ の連続ブロックを単位として復元抽出。 自己相関を保つ
residual bootstrap回帰モデル$\hat{y}_i$ を固定し、 残差 $\hat{\varepsilon}_i$ を復元抽出して新しい $y_i^* = \hat{y}_i + \hat{\varepsilon}^*_i$ を作る
wild bootstrap不等分散の回帰残差を ±1 のランダム符号で乗算。 heteroskedasticity-robust
BCa bootstrap分布が歪む場合パーセンタイル CI にバイアス補正と加速度を加える。 sciPy のデフォルトの 1 つ
bootstrap-t (studentized)正確な被覆率が必要各複製で SE も計算し、 t 統計量の分布を bootstrap。 計算コストは高いが被覆率は最良
m-out-of-n bootstrap分位点・末尾統計量サイズ m < n のサブサンプル。 standard bootstrap が破綻する状況で使用
Bayesian bootstrapベイズ的解釈復元抽出ではなく、 ディリクレ分布から重みを引いて加重平均。 事後分布の近似に使える
jackknifeブートの祖先n 個から 1 個ずつ抜いた n 個の標本で統計量を計算。 SE の linearization 近似
permutation test仮説検定の親戚群ラベルをシャッフルして H₀ 下の分布を作る。 同じ「再標本化」族

使い分けの一行ルール:データが iid で分布の仮定を避けたい → standard nonparametric bootstrap。 時系列 → block。 分布の歪みが強い → BCa。 厳密な CI 被覆率が必要 → bootstrap-t

📚 関連グループ教材

🗺 概念マップ — ブートストラップを取り巻く位置関係

ブートストラップ法は 「リサンプリング法」 という大きな枠組の一員。 ファミリー全体を見渡すと位置づけが鮮明になります:

リサンプリング法(Resampling Methods)
├── ブートストラップ(with replacement, 同サイズ)
│   ├── nonparametric bootstrap(古典)
│   ├── parametric bootstrap
│   ├── block bootstrap(時系列)
│   ├── wild bootstrap(不等分散)
│   └── Bayesian bootstrap
├── ジャックナイフ(leave-one-out, no replacement)
├── 並べ替え検定(permutation, labels shuffle)
├── クロスバリデーション(without replacement, k-fold)
│   ├── k-fold CV
│   ├── leave-one-out CV
│   └── nested CV
└── サブサンプリング(m < n, without replacement)
  

いずれも「計算機で繰り返し再標本化することで、 統計量や予測モデルのブレや汎化性能を直接測る」という共通哲学。 解析的に難しい問題を計算量で乗り越える 20 世紀後半の統計学の革命でした。

📚 さらに学ぶには

このサイト内

推奨書籍・教材

オンライン教材

困ったときは

「ブートストラップ CI が広すぎる」「BCa と percentile で結果が違う」「収束しない」など困ったら、 (1) B をもっと大きく、 (2) BCa を試す、 (3) サンプルサイズと統計量の組合せが極端統計量でないか確認、 (4) 観測の独立性を再点検。 Cross Validated(Stack Exchange)で類例を探すのも有効。

🧠 Bootstrap の哲学 — 「データを母集団と思え」

ブートストラップは Efron (1979) の発明。 「手元データの経験分布 $\hat F_n$ を真の分布 $F$ の代理にする」というシンプルな原理で、 解析的には困難な統計量の標準誤差・信頼区間を計算機シミュレーションで導きます。

$$X^{*} \sim \hat F_n \quad \Leftrightarrow \quad X^{*} = X_I, \quad I \sim \text{Unif}\{1,\ldots,n\}$$

SSDSE-B-2026 の 47 都道府県平均人口の SE を求めたいとき、 通常は中心極限定理で $\hat\sigma/\sqrt{n}$ を計算しますが、 ブートストラップなら「中央値の SE」「相関係数の CI」のような 解析公式が存在しない統計量でも一貫した方法で扱えます。

📐 5 種類のブートストラップ CI

手法CI 公式長所短所推奨
Percentile$[\hat\theta^*_{(\alpha/2)}, \hat\theta^*_{(1-\alpha/2)}]$シンプル偏り補正なし初学者向け
Basic$[2\hat\theta - \hat\theta^*_{(1-\alpha/2)}, 2\hat\theta - \hat\theta^*_{(\alpha/2)}]$偏り部分補正対称性に依存中級
Bootstrap-t$\hat\theta \pm t^*_{(1-\alpha/2)} \cdot \hat{SE}^*$高精度計算重い理論派
BCa加速度バイアス補正最も正確実装複雑推奨デフォルト
ABC解析的版 BCa高速 BCa一階近似研究用

BCa (Bias-Corrected and accelerated) は二階精度で、 平均値・中央値・分位点・相関のいずれにも適切な CI を与えます。 scipy.stats.bootstrap は BCa をデフォルトに採用しています。

🐍 SSDSE-B での Bootstrap 完全実装

SSDSE-B-2026 の 47 都道府県平均人口の 95% BCa CI を計算:

import pandas as pd
import numpy as np
from scipy import stats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
pop = df.iloc[:, 3].values

# 1) scipy の BCa (推奨)
res = stats.bootstrap((pop,), np.mean,
                      confidence_level=0.95, method='BCa',
                      n_resamples=9999, random_state=0)
print(f'BCa CI: {res.confidence_interval}')

# 2) 自作 percentile
B = 10000
rng = np.random.default_rng(0)
boots = [rng.choice(pop, len(pop), replace=True).mean() for _ in range(B)]
lo, hi = np.percentile(boots, [2.5, 97.5])
print(f'Percentile CI: [{lo:.0f}, {hi:.0f}]')

結果例:BCa CI ≈ [1,580,000, 4,210,000]、 SE ≈ 680,000 人。 「47 都道府県平均が将来 ±70 万人ブレうる」ことが直感的に分かります。

📅 時系列ブートストラップ — ブロック法

時系列データへの単純ブートストラップは間違い。 時間相関が壊されるためです。 解決策が ブロックブートストラップ

from arch.bootstrap import StationaryBootstrap, CircularBlockBootstrap

# 時系列データの想定(年次パネル)
sb = StationaryBootstrap(10, pop)  # 平均ブロック長 10
ci = sb.conf_int(np.mean, reps=5000, method='bca')
print(f'時系列 BCa CI: {ci}')

📊 回帰での Bootstrap — 4 流儀

回帰モデルでのブートストラップは「ペア法」と「残差法」の二択。

手法再標本化対象長所短所
Pair bootstrap$(x_i, y_i)$ペア誤分散・非線形に頑健$X$ デザインが変動
Residual bootstrap残差 $\hat e_i$デザイン固定等分散性仮定必要
Wild bootstrap残差 × 乱数異分散対応マルチプライヤ選択
Bayesian bootstrap重みディリクレ事後分布解釈理論的やや異色

SSDSE-B-2026 で「人口 → GDP」回帰の係数 95% CI を求めるなら、 まずペア法(最も頑健)を使い、 余裕があれば Wild bootstrap も試して頑健性を確認するのが定石。

⚠️ Bootstrap の追加的落とし穴(10 個)

  1. $B$ が少なすぎる:$B \ge 1000$ は必須、 95% CI なら $\ge 5000$、 99% CI なら $\ge 10000$。
  2. 独立性が崩れている:時系列・クラスタデータには専用ブートストラップを。
  3. 極値統計量への適用:最大値・最小値の Bootstrap は不一致になりやすい。
  4. 小標本での過信:$n < 30$ では真の被覆率が 90% を下回ることも。
  5. ブロック長の選択ミス:時系列ブロック法では $\ell \approx n^{1/3}$ が経験則。
  6. BCa の計算コスト過小評価:jackknife を要するので $n$ 倍重い。
  7. マルチコリニア状況での回帰:ペア法でも係数の符号が反転することがある。
  8. 不均衡データ:少数クラスがブートサンプルに含まれないことがある。 stratified bootstrap で対処。
  9. 並列化忘れ:joblib の Parallel を使えば $B=10^4$ も数秒に。
  10. シード未固定:再現性のため random_state を必ず設定。

🎓 Bootstrap の理論的保証 — どこまで信頼できるか

Bootstrap の理論的正当性は「データから生成された経験分布が真の分布に収束する」 (Glivenko-Cantelli) と「平滑な統計量に対する Bootstrap が一致推定量になる」 (Singh, 1981) で保証されています。

一致性の条件は意外と厳しい。 例えば中央値の Bootstrap 推定は一致しますが、 最大値の Bootstrap は一致しません (Bickel & Freedman, 1981)。 つまり「すべての統計量に万能ではない」のが Bootstrap の重要な制約。

Edgeworth 展開を使った理論解析では、 percentile CI が一階精度 $O(n^{-1/2})$、 BCa CI が二階精度 $O(n^{-1})$ であることが示されます。 つまり BCa は通常正規 CI と同じ精度です。

🌐 リサンプリング家系図

Bootstrap の親戚たち:

💼 Bootstrap 実務応用 8 分野

実務で Bootstrap が役立つシーン:

📑 Bootstrap 古典論文集

🔗 関連用語(拡張版)

❓ よくある質問(FAQ)

Q. $B$ 回はいくつあれば?

A. SE 推定なら $B=200$、 90% CI なら $B=1000$、 95% CI なら $B=5000$、 99% CI なら $B=10000$ が経験則。 BCa はさらに $n$ 倍重い jackknife を必要とします。

Q. Bootstrap と CLT の使い分けは?

A. CLT は「標本平均が正規」と言うだけ。 中央値・分位点・相関・複合指標などは CLT が直接適用できないので Bootstrap。 また小標本では CLT の収束が遅く Bootstrap の方が信頼できることも。

Q. 時系列に普通の Bootstrap は使える?

A. 使えません。 時間相関を壊すので。 Block Bootstrap、 Stationary Bootstrap、 または AR モデルの残差 Bootstrap を使います。

Q. Bootstrap が「失敗」する場合は?

A. 極値統計量(最大・最小)、 「データ全体の関数」、 重い裾を持つ分布、 強い従属性、 小標本($n < 10$)など。 こうした場合は m-out-of-n Bootstrap や subsampling が代替。

Q. BCa CI と percentile CI、 どっち?

A. 理論的・実用的に BCa が優位。 percentile は教育用・対称分布の単純なケース。 scipy.stats.bootstrap のデフォルトが BCa です。

Q. Bayesian Bootstrap との違いは?

A. 通常 Bootstrap は離散的に重複度を変える(多項分布)。 Bayesian Bootstrap は連続的にディリクレ重みを与える。 結果は漸近的に等価だが、 事後分布解釈が明示的。

Q. ペア法 vs 残差法の使い分けは?

A. 異分散・誤特定が疑われるなら必ずペア法。 デザイン行列を保ちたい・等分散仮定が妥当なら残差法。 迷ったらペア法(より頑健)。

Q. 並列化のコツは?

A. `joblib.Parallel(n_jobs=-1)(delayed(boot_func)(rng) for _ in range(B))`。 シードを各ジョブに分けて再現性確保。

🏛 Bootstrap の歴史

💼 産業応用事例

臨床試験

治療効果の SE と CI、 ARR (Absolute Risk Reduction) の不確実性。

ファイナンス

VaR、 シャープレシオ、 トラッキングエラーの CI。

機械学習

Bagging (Random Forest)、 予測 CI、 特徴重要度の SE。

計量経済学

弾力性・処置効果の SE、 GMM 推定量の不確実性。

品質管理

CpK、 Process Capability の CI。

A/B テスト

効果サイズの Bootstrap CI、 ベイズ Bootstrap で事後分布。

生物統計

マイクロアレイの遺伝子発現比較、 補正後 p 値。

スポーツ分析

プレーヤー指標の CI、 期待値計算。

🔬 Bootstrap の収束精度

Hall (1992) の Edgeworth 解析によると、 Bootstrap CI の被覆精度は手法によって異なります:

CI 手法片側精度両側精度補正
通常正規$O(n^{-1/2})$$O(n^{-1})$なし
Percentile$O(n^{-1/2})$$O(n^{-1})$なし
Bootstrap-t$O(n^{-1})$$O(n^{-2})$studentized
BCa$O(n^{-1})$$O(n^{-2})$bias+accel

BCa と Bootstrap-t が二階精度 ($O(n^{-2})$) で最良。 通常正規 CI と percentile CI は同精度ですが、 偏った分布では数値的に大きく異なります。

計算量と精度のトレードオフ

「Bootstrap が一致推定量にならない」例

Bickel & Freedman (1981) は以下の場合に Bootstrap が一致推定量にならないことを示しました:

こうしたケースには m-out-of-n Bootstrap、 subsampling、 または直接的シミュレーションが代替手段です。