自由集会2003 (「R」 についてはこちらを参照)
DATE: 2003/03/29 17:29:48 +0900 更新

「R」を用いた
ブーツストラップ法の講義資料

この解説は三中信宏さん (minaka@affrc.go.jp) が統計学の集中講義 (信州大学 2002 年 12 月) で使用されたものです. 原文 (テキスト) は 2002 年 12 月 26 日に 生物統計学メイリングリスト biometry に投稿されました. 三中さんのご了承をいただき, その資料を HTML 化して公開します. (HTML 化: 久保拓弥 kubo@ees.hokudai.ac.jp)

内容

ブーツストラップ法――経験的密度関数・信頼区間・誤差評価

「ブーツストラップ」とは計算統計学のひとつの手法で, データからの無作為再抽出を繰り返すことにより, 推定量(たとえば標本平均のような)の誤差(バラツキ)を評価したり, 密度関数を経験的に推定したりする. 特定のパラメトリックな確率分布(たとえば正規分布のような)を前提とせず, むしろデータそのものから推定量の確率分布を導き, 誤差評価をしたり, 信頼区間をつくろうというノンパラメトリックな「精神」の発露である.

以下では,Rを用いて,この「ブーツストラップ精神」なるものを 体験してみよう.

●数列テストデータによるブーツストラップ原理の説明

> data <- c(0,1,2,3,4,5,6,7,8,9)
	# 数列{0,1,2,...,9}をテストデータとして data に格納
> var(data)	# data の分散
[1] 9.166667
---

ここで var(data) は分散の不偏推定値(平方和/自由度) であることに注意.下記に検算結果を記す.

	deviation <- numeric(10)
		# deviation を長さ 10 の数値ベクトルとする
	> for (i in 1:10) deviation[i] <- data[i] - mean(data)
		# 偏差=データ−平均を求め deviation に格納
	> ms <- (sum(deviation^2))/(10-1)
		# 分散=平方和/自由度を ms に格納
	> ms	# var(data)との一致を確認
	[1] 9.166667
---
> var(data)/10	# data の標本平均の分散
[1] 0.9166667

> sample(data, 10, replace=T)
	# data から重複を許して10標本を無作為再抽出(ブーツストラップ)
 [1] 7 7 5 5 3 7 4 8 9 6
	# 以下,再抽出を繰り返してみる
> sample(data, 10, replace=T)
 [1] 2 1 7 3 0 2 4 8 5 0
> sample(data, 10, replace=T)
 [1] 4 6 7 1 4 7 7 8 4 5
> sample(data, 10, replace=T)
 [1] 9 8 1 7 5 0 5 7 5 7
> sample(data, 10, replace=T)
 [1] 3 2 0 8 7 1 2 4 7 7
> sample(data, 10, replace=T)
 [1] 6 7 1 4 9 5 8 5 5 9

> mean(data)	# 元データ(data)の標本平均
[1] 4.5
> mean(sample(data, 10, replace=T))	# ブーツストラップ1の平均
[1] 4.8
> mean(sample(data, 10, replace=T))	# ブーツストラップ2の平均
[1] 5.7
> mean(sample(data, 10, replace=T))	# 以下,同じ操作.
[1] 3.5
> mean(sample(data, 10, replace=T))
[1] 5.4

> bootsrtap <- numeric(10)
	# bootstrap を長さ10の数値ベクトルとしてオブジェクト定義
> for (i in 1:10) bootstrap[i] <- mean(sample(data, 10, replace=T))
	# 10回のブーツストラップ反復による平均値を bootstrap に格納
> bootstrap
	# 計算結果の表示
 [1] 3.4 5.0 5.2 4.4 4.3 4.6 4.8 3.8 5.3 3.8
> mean(bootstrap)	# 平均
[1] 4.46
> var(bootstrap)	# 分散(上で求めた分散推定値よりもかなり小さい)
[1] 0.4115556

> bootstrap <- numeric(1000)
> for (i in 1:1000) bootstrap[i] <- mean(sample(data, 10, replace=T))
	# ブーツストラップ反復の回数を1000回にしてみる
> var(bootstrap)	# 分散(100回反復のときよりも大きい)
[1] 0.7411788

●正規乱数をデータとする事例――標本平均のブーツストラップ誤差評価

> data <- c(rnorm(1000, mean=0, sd=1)) 
	# 標準正規分布 N(0,1) からの1000無作為標本を data に格納

> data	# data の中身
   [1]  0.235074605 -1.356050398  0.267868209  0.087841559  1.012879979
///////////////////////////////////////////////////////////////////////
 [996]  1.788910285 -1.358704507  0.035108314  0.708958886  0.359765422

> mean(data)
[1] 0.01827712	# data の標本平均

> sample(data, 1000, replace=T) 
	# data から重複を許して1000個の標本を無作為再抽出(ブーツストラップ)
   [1]  0.254607843  0.613191045 -1.417716944 -0.008924308  0.223065333
///////////////////////////////////////////////////////////////////////
 [996]  0.474348840  2.061109996  1.757300192 -0.410549785 -0.715952569

> set.seed(101)
	# 擬似乱数の seed を「101」に設定
> m <- 1000 
	# ブーツストラップ反復回数を m=1000 に設定
> replicate1000 <- numeric(m) 
	# "replicate1000" を長さ1000の数値ベクトルとしてオブジェクト定義
> for (i in 1:m) replicate1000[i] <- mean(sample(data, m, replace=T)) 
	# data からの m 回ブーツストラップを実行し,結果をreplicate1000に格納
> mean(replicate1000)
[1] 0.01801577		# ブーツストラップ平均
> var(replicate1000)
[1] 0.0009630001	# ブーツストラップ分散
> sd(replicate1000)
[1] 0.03103224		# ブーツストラップ標準偏差

> m <- 500		# ブーツストラップ反復を m=500 として実行
> replicate500 <- numeric(m)
> for (i in 1:m) replicate500[i] <- mean(sample(data, m, replace=T))
> mean(replicate500)
[1] 0.01753351
> var(replicate500)
[1] 0.002081382
> sd(replicate500)
[1] 0.04562217

> m <- 100		# ブーツストラップ反復を m=100 として実行
> replicate100 <- numeric(m)
> for (i in 1:m) replicate100[i] <- mean(sample(data, m, replace=T))
> mean(replicate100)
[1] 0.0378861
> var(replicate100)
[1] 0.00949725
> sd(replicate100)
[1] 0.09745383

			# m=100, 500, 1000 の結果をヒストグラム表示
> hist(replicate100, freq=F)
hist100
> hist(replicate500, density=25, freq=F, add=T)
hist100 + 500
> hist(replicate1000, density=25, angle=135, freq=F, add=T)
hist100 + 500 + 1000

●ヒストグラムからの確率密度関数の推定と信頼区間の計算

ブーツストラップによって求められた推定量(ここでは標本平均) のバラツキをヒストグラムとして描画できたならば, それに基づいて確率密度関数を推定することが可能である. 得られた経験的密度関数を用いて, 推定量の信頼区間を設定することもできる. この密度関数の経験的推定には, ある基底関数(kernel)を用いたヒストグラムの平滑化(smoothing) という手法が用いられている. 天下り式の確率密度関数をデータに当てはめるのではなく, むしろデータから逆に密度関数そのものを推定しようというスタンスを取る.

> library(MASS)
	# ライブラリー MASS をインストールする.
	# これは "Modern Applied Statistics with S" のためのライブラリー

> data <- c(rnorm(1000, mean=0, sd=1)) 
	# 標準正規分布から1000乱数をデータとして data に格納
> set.seed(101)
	# 擬似乱数シードを 101 に設定
> m <- 1000
	# ブーツストラップ反復回数は m=1000回
> replicate <- numeric(m)
	# replicate は長さ m のベクトル
> for (i in 1:m) replicate[i] <- mean(sample(data, m, replace=T))
	# data からのブーツストラップ計算
> mean(replicate)	# 平均
[1] -0.008360919
> var(replicate)	# 分散
[1] 0.001120811
> sd(replicate)		# 標準偏差
[1] 0.03347851

> truehist(replicate, h=0.01)
	# 得られた1000個のブーツストラップ値をヒストグラム表示
truehist
> lines(density(replicate, width="SJ-dpi", n=256))
	# このヒストグラムから経験的密度関数を推定する
truehist + density
> quantile(replicate, p=c(0.025, 0.975))
	# 推定された密度関数から5%信頼区間を求める.
	# 下側2.5%点と上側2.5%点は下記のように表示される.

	       2.5%       97.5% 
	-0.07269752  0.05757690 

コマンド「density」を用いたこの密度関数推定は, ブーツストラップのみにかぎらず,もっと広く利用できる.

●コマンド「boot」の利用

Rにはブーツストラップに特化したコマンド「boot」 がライブラリに用意されている. 上述の操作は, この「boot」を用いることにより, 格段に単純化される. たとえば, 数列データを例とする, ブーツストラップ計算は下記の通り:

> library(boot)
	# ライブラリ「boot」をインストールする
> data <- c(0,1,2,3,4,5,6,7,8,9)
	# 数列{0,1,2,...,9}を data に格納
> set.seed(101)
	# 乱数シードを「101」に設定
> boot(data, function(x, i)mean(x[i]), R=1000)
	# ブーツストラップの設定
	1)「data」:
		再抽出対象となるデータ名.ここでは"data".
	2)「function(x, i)mean(x[i])」:
		誤差評価を行なう統計量の関数指定.ここでは標本平均.
	3)「R」:
		ブーツストラップ反復回数.ここでは1000回.

以下は,計算結果:

	ORDINARY NONPARAMETRIC BOOTSTRAP

	Call:
	boot(data = data, statistic = function(x, i) mean(x[i]), R = 1000)

	Bootstrap Statistics :
	    original  bias    std. error
	t1*      4.5 -0.0101   0.9023204

「ブーツストラップ統計量」として出力されるのは, 元データの平均(original) ・ブーツストラップ反復から得られた平均の original からのバイアス(bias) ・ブーツストラップから得られた標本平均の標準誤差(std. error) である.

なお「boot」は他にも多くの機能をもっており, 上述のような, ノンパラメトリック・ブーツストラップだけでなく, パラメトリック・ブーツストラップも実行できる. 詳細は help(boot) を参照していただきたい.

ジャックナイフ法による誤差評価

ジャックナイフによる誤差評価は,データからの重複を許さない (replace=F)再抽出の反復に基づく.したがって, 反復回数を m, 再抽出数を k (< m) で指定したとき,

> replicate <- numeric(m)
> for (i in 1:m) replicate[i] <- mean(sample(data, k, replace=F))
> var(replicate)

によって,標本平均の誤差を求めることができる.たとえば, 下記のように:

> data <- c(0,1,2,3,4,5,6,7,8,9)
	# データ読みこみ
> m <- 10	# 再抽出回数
> k <- 9	# 除去数1の delete-one jackknife
> replicate <- numeric(m)
> for (i in 1:m) replicate[i] <- mean(sample(data, k, replace=F))
> var(replicate)
[1] 0.08079561

> m <- 10	# 再抽出回数
> k <- 5	# 半数除去の delete-half jackknife
> replicate <- numeric(m)
> for (i in 1:m) replicate[i] <- mean(sample(data, k, replace=F))
> var(replicate)
[1] 0.6204444

自由集会2003 にもどる