logo
Loading...

【QA】甚麼是 Bootstrapping (拔靴法)? - 【教材專區】學習AI有困難? 讓Cupoy助教來幫你! - Cupoy

Statistics is the science of learning from experience. 翻譯成中文,統計就是從經驗中學習的科學。 本質上統計是用來嘗試回答3個基本的問題: D...

Statistics is the science of learning from experience. 翻譯成中文,統計就是從經驗中學習的科學。 本質上統計是用來嘗試回答3個基本的問題: Data Collection: How should I collect my data? 舉例來說:如何做實驗收集資料 Summary: How should I analyze and summarize the data that I’ve collected? 舉例來說:如何從資料中分析並得到一個結果,也許是圖表或是在一定信賴區間(95%)下的數值分布區間 Statistical Inference: How accurate are my data summaries? 舉例來說:我的結果有多可信或多準確 第3點,所謂的統計推論(statistical inferences)就是我們的Bootstrap所發揮作用的地方。 我們接下來看看Bootstrap的效果與目的。 根據一些名間傳言,Bootstrap的命名由來是來自於Adventures of Baron Munchausen這部作品,有一幕是主角被困在泥沼時脫下靴子用來幫助自己脫離泥沼,因此稱為拔靴法或拔靴自助法(參考連結),自助是這裡很重要的概念,Bootstrap就是不斷從同一個資料集中學習並實現減少variance的效果。 首先我們看看Bradley Efron的An Introduction to the Bootstrap(連結)中的範例,給定兩個資料集,分別是給予aspirin(阿斯匹靈)和(placebo)安慰劑兩個實驗組, 給予aspirin的組別中共有11037個人,其中有119個發生中風 給予placebo的組別中共有11034個人,其中有98個人發生中風 我們用python來模擬這個實驗條件,code如下: import numpy as np import random # 1代表發生中風的樣本,0代表沒有發生的樣本 lis1 = [1]*119 + [0]*(11037-119) lis2 = [1]*98 + [0]*(11034-98) 我們可以估計一個theta,用來計算所有病患中,給予阿斯匹靈的患者發生中風的比例,對比給予安慰劑的患者發生中風的比例,這裡可以得到1.21這個數值,單從結果上來看給予阿斯匹靈是很危險的。 ratio = lambda lis: sum(lis)/len(lis) theta = ratio(lis1)/ratio(lis2) print('患者中風比值:給予阿斯匹靈/給予安慰劑:', theta) 接下來我們用bootstrap來估計一個theta在95%信心水準下的信賴區間。 首先定義用來計算theta^的函式 def props(lis, k):  a = random.choices(lis, k=k) # 從原始資料中抽出長度為k的子集合  return sum(a)/len(a) # 下面的k可以選擇任意小於list總長的數 theta = props(lis1, k=6666) / (props(lis2, k=8787)+1e-12) # 加上一個微小常數避免分母0 print(theta) Bootstrap的本質是基於大數法則(**Law of large numbers)**的重複抽樣,而每一次抽樣並不會把所有資料抽出來,也就是上面的k值不會等於總資料長度,而k值越大,能夠更快的收斂,但k值足夠小降低variance的效果才會明顯。 那麼上面只有抽樣一次而已,接下來我們用一個for迴圈進行重複抽樣。 theta_lis = [] replica = 1000 for loop in range(replica):  theta = props(lis1, k=6666) / (props(lis2, k=8787)+1e-12)  theta_lis.append(theta) theta_lis = sorted(theta_lis) # 排序theta_lis 首先設定一個空集合用來收集每次實驗得到的theta^,然後設定要重複的次數replica=1000,接下來我們可以觀察theta_lis的一些統計量。 你會發現,theta_lis的平均值與前面我們從整個母群體估計出來的theta是非常靠近的,就只差一個標準差而已。這反映了Bootstrap的精神:我們不需要直接看到整個母群體(實務上,大部分的情況我們也無法觀察真正的母群體),而是透過不斷抽樣子集合,這些子集合的平均應該能夠趨近母群體的平均值,並且這些子集合的分布能夠很好的反應母群體的分布。 Bootstrap還有一個很好用的地方在於信賴區間的估計,我們手上的theta_lis是經過排序的一個histrogram,當我們要計算95%的信賴區間時,可以直接找2.5百分位的數值和97.5百分位的數值,他就是信賴區間的近似解。如下面所示的[0.86, 1.65] 以上就是Bootstrap的介紹,完整程式碼如下: import numpy as np import random # 1代表發生中風的樣本,0代表沒有發生的樣本 lis1 = [1]*119 + [0]*(11037-119) lis2 = [1]*98 + [0]*(11034-98) ratio = lambda lis: sum(lis)/len(lis) theta = ratio(lis1)/ratio(lis2) print('患者中風比值:給予阿斯匹靈/給予安慰劑:', theta) # Bootstrap方法 def props(lis, k):  a = random.choices(lis, k=k)  return sum(a)/len(a) # 下面的k可以選擇任意小於list總長的數 theta = props(lis1, k=6666) / (props(lis2, k=8787)+1e-12) print(theta) theta_lis = [] replica = 1000 for loop in range(replica):  theta = props(lis1, k=6666) / (props(lis2, k=8787)+1e-12)  theta_lis.append(theta) theta_lis = sorted(theta_lis) print(np.mean(theta_lis), np.std(theta_lis)) # 近似的母體平均值和標準差 print(np.quantile(theta_lis, (0.025, 0.975))) # 95%下的信賴區間