• home
  • about
  • 全ての投稿
  • ソフトウェア・ハードウェアの設定のまとめ
  • 分析関連のまとめ
  • ヘルスケア関連のまとめ
  • 生涯学習関連のまとめ

ブートストラップ法

date: 2019-01-07 excerpt: ブートストラップ法について

tag: ブートストラップ法statistics


ブートストラップ法について

概要

  • 復元抽出にて何度もサンプルすることで、その統計値の分布を(できるだけロバストに)知る
  • ブートストラップの名前の由来
    • 靴のブートストラップという紐を用いて自分自身を持ち上げるという自己完結できる手段・プロセスを示すものから
  • 復元抽出でのサンプルサイズと求めたい統計量の分散は関連する

numpyで復元抽出

# np.random.choiceで復元抽出で重なりあり
src = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
display(np.sort(np.random.choice(src, 10))) # array([1, 1, 3, 3, 4, 6, 6, 6, 7, 8])
display(np.sort(np.random.choice(src, 10))) # array([ 2,  3,  6,  6,  6,  7,  7,  8,  9, 10])
display(np.sort(np.random.choice(src, 10))) # array([ 4,  5,  6,  7,  8,  9,  9,  9, 10, 10])

具体例(身長のデータが10サンプルのとき、95%信頼区間の近似値を求める)

最初の10サンプルを適当な正規分布から生成

import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
 
np.random.seed(1)
 
pop_mean = 171.2
pop_std = 6
sample_size = 10
 
sample = np.random.normal(pop_mean, pop_std, sample_size)
sample_mean = np.mean(sample)
sample_uvar = np.var(sample, ddof=1)
sample_std = np.sqrt(sample_uvar)
display(sample)

"""
array([180.94607218, 167.52946152, 168.03096949, 164.76218827,
       176.39244578, 157.39076782, 181.66887059, 166.63275859,
       173.11423458, 169.70377775])
"""

ブートストラップでサンプルサイズ増やす

n_boots = 10000
resample_means = []
for i in range(n_boots):
    resample = np.random.choice(sample, 10)
    resample_means.append(np.mean(resample))

95%の範囲のデータ

conf_prob = np.array([0.025, 0.975])
resample_conf = np.percentile(resample_means, conf_prob*100)
display(resample_conf)
"""
array([166.26765934, 175.09959133])
"""

t分布を用いての95%の信頼区間

sample_conf = sample_mean + stats.t.ppf(conf_prob, df=sample_size-1) * np.sqrt(sample_uvar / sample_size)
display(sample_conf)
"""
array([165.22915528, 176.00515403])
"""

具体例(少ないデータから相関を求めたい時の信頼性を上げる)

テストの成績が以下の結果であったとき、Eng <-> Math, Math <-> Sciの相関をブートストラップする

  Eng Math Sci
0 60 88 90
1 89 82 87
2 65 60 60
3 60 65 61
4 73 85 82
5 52 56 53
6 70 57 60
7 65 75 74
8 65 82 85
9 70 90 95

結果

コード

df = pd.DataFrame(total.T)

corrs = []
for n in tqdm(range(10**3 * 5)):
    df_cache = []
    for n in range(len(df)):
        tmp = df.sample(frac=1).iloc[0].to_dict()
        df_cache.append(tmp)
    corr = pd.DataFrame(df_cache).corr()
    corr_sci_math = float(corr.loc[corr.index == "Sci", "Math"])
    corrs.append( corr_sci_math )
corrs
ax0 = sns.distplot(corrs)

復元抽出でのサンプルサイズと求めたい統計量の分散は関連する

  • サンプルサイズが大きいほど、統計量の分散は小さくなる
  • サンプルサイズが小さいほど、統計量の分散は大きくなる

Google Colabでの実験

  • boot strapでのサンプリングの例

参考

  • ブートストラップサンプリング/TauStation
  • ブートストラップ法/Qiita


ブートストラップ法statistics Share Tweet