统计学中的Bootstrap方法(有放回的抽样)

介绍

\quad \quad Bootstrap又称自展法、自举法、自助法、靴带法 , 是统计学习中一种重采样(Resampling)技术,用来估计标准误差、置信区间和偏差

\quad \quad Bootstrap是现代统计学较为流行的一种统计方法,在小样本时效果很好。机器学习中的Bagging,AdaBoost等方法其实都蕴含了Bootstrap的思想,在集成学习的范畴里 Bootstrap直接派生出了Bagging模型.

用子样本来类比总体

举例
\quad \quad 我要统计鱼塘里面的鱼的条数,怎么统计呢?假设鱼塘总共有鱼1000条,我是开了上帝视角的,但是你是不知道里面有多少。

步骤:

  1. 承包鱼塘,不让别人捞鱼(规定总体分布不变)。
  2. 自己捞鱼,捞100条,都打上标签(构造样本)
  3. 把鱼放回鱼塘,休息一晚(使之混入整个鱼群,确保之后抽样随机)
  4. 开始捞鱼,每次捞100条,数一下,自己昨天标记的鱼有多少条,占比多少(一次重采样取分布)。
  5. 重复3,4步骤n次。建立分布。

(原理是中心极限定理)

假设一下,第一次重新捕鱼100条,发现里面有标记的鱼12条,记下为12%,放回去,再捕鱼100条,发现标记的为9条,记下9%,重复重复好多次之后,假设取置信区间95%,你会发现,每次捕鱼平均在10条左右有标记,所以,我们可以大致推测出鱼塘有1000条左右。其实是一个很简单的类似于一个比例问题。这也是因为提出者Efron给统计学顶级期刊投稿的时候被拒绝的理由–“太简单”。这也就解释了,为什么在小样本的时候,bootstrap效果较好,你这样想,如果我想统计大海里有多少鱼,你标记100000条也没用啊,因为实际数量太过庞大,你取的样本相比于太过渺小,最实际的就是,你下次再捕100000的时候,发现一条都没有标记,就尴尬了。。。

上述是通过 Bootstrap 方法对鱼塘中鱼的数目进行估计,通过这个举例我们可以总结如下:设总体的分布 F F F未知,但已经有一个容量为 n n n的来自分布 F F F的数据样本,通过有放回抽样的方法抽取 m m m个容量为 n n n的样本,对这 m m m个抽样容量统一计算结果来估计原始的总体分布 F F F, 称为Bootstrap方法

下面继续介绍,如果要估计出某个特征数据的原始均值,标准差,方差等情况,应该是怎么样的呢?

传统估计方法

传统方法中一般会考虑直接使用样本方差(sample variance)来作为估计值。
μ ^ = x ˉ = ∑ i = 1 n x i n \hat{\mu} = \bar{x} = \frac{\sum_{i=1}^nx_i}{n} μ^=xˉ=ni=1nxi

S ^ 2 = ∑ i = 1 n ( x i − x ˉ ) 2 n − 1 \hat{S}^2 = \frac{\sum_{i=1}^n(x_i - \bar{x})^2}{n - 1} S^2=n1i=1n(xixˉ)2
σ ^ = S 2 n \hat{\sigma} = \frac{S^2}{n} σ^=nS2

其中: μ ^ \hat{\mu} μ^ 为均值估计, S ^ 2 \hat{S}^2 S^2 为方差估计值, σ ^ \hat{\sigma} σ^ 为标准差估计值

比如有三个样本 X = 1 , 2 , 3 X = 1, 2, 3 X=1,2,3,求样本的方差作为估计值。

Bootstrap 方法

放回抽样,比如上述例子中,有可能第一次抽到 ①,第二次也抽到 ①,第三次还是抽到 ①,对三个样本 X = 1 , 2 , 3 X = 1, 2, 3 X=1,2,3,放回抽样 1000 次,用这 1000 次抽样的结果分别计算出各自的均值 x ˉ \bar{x} xˉ , 然后再利用这 1000 个值,计算其整体的均值,方差等统计量,这就是 Bootstrap 方法,如下图所示:

实际案例

假设有两个金融资产 X X X Y Y Y,现在想要合理配置这两个资产,使得其资产组合的风险最小。也就是找到一个 α \alpha α,使得 V a r ( α X + ( 1 − α ) X ) Var(\alpha X + (1 - \alpha) X) Var(αX+(1α)X)最小。(Var 表示方差)

将上式展开得到 α 2 V a r ( X ) + ( 1 − α ) 2 V a r ( X ) + α ( 1 − α ) C o v ( X Y ) \alpha^2 Var(X) + (1 - \alpha)^2Var(X) + \alpha(1 - \alpha)Cov(XY) α2Var(X)+(1α)2Var(X)+α(1α)Cov(XY),首先,通过对 α \alpha α 求一阶导等于0,再求二阶导大于0,得到最优 α \alpha α 表达式如下:
α = σ Y 2 − σ X Y σ X 2 + σ Y 2 − 2 σ X Y \alpha = \frac{\sigma_Y^2 - \sigma_{XY}}{\sigma_X^2 + \sigma_Y^2 - 2\sigma_{XY}} α=σX2+σY22σXYσY2σXY

其中 σ X 2 = V a r ( X ) , σ Y 2 = V a r ( Y ) , \sigma_X^2 = Var(X), \sigma_Y^2 = Var(Y), σX2=Var(X),σY2=Var(Y), and σ X Y = C o v ( X , Y ) \sigma_{XY} = Cov(X, Y) σXY=Cov(X,Y)

实际的 σ X 2 , σ Y 2 , σ X Y \sigma_X^2, \sigma_Y^2, \sigma_{XY} σX2,σY2,σXY 的值并不知道,只能通过现有的样本 X X X Y Y Y 对其进行估计,并用估计值 σ ^ X 2 , σ ^ Y 2 \hat{\sigma}_X^2, \hat{\sigma}_Y^2 σ^X2,σ^Y2 以及 σ ^ X Y \hat{\sigma}_{XY} σ^XY 计算出估计值 α ^ \hat{\alpha} α^,如下:

α ^ = σ ^ Y 2 − σ ^ X Y σ ^ X 2 + σ ^ Y 2 − 2 σ ^ X Y \hat{\alpha} = \frac{\hat{\sigma}_Y^2 - \hat{\sigma}_{XY}}{\hat{\sigma}_X^2 + \hat{\sigma}_Y^2 - 2\hat{\sigma}_{XY}} α^=σ^X2+σ^Y22σ^XYσ^Y2σ^XY

现在的任务就是用一种合理方式去估计 σ ^ X 2 , σ ^ Y 2 \hat{\sigma}_X^2, \hat{\sigma}_Y^2 σ^X2,σ^Y2 以及 σ ^ X Y \hat{\sigma}_{XY} σ^XY,Bootstap 方法如下:对样本进行有放回采样 1000 次,每次采样 100 个样本,计算每个抽样结果的 α ^ \hat{\alpha} α^,在这 1000 个 α ^ \hat{\alpha} α^ 上计算 α ^ \hat{\alpha} α^ 的均值作为 α \alpha α 的估计结果:

可以发现,通过Bootstrap方法,竟然不仅可以估计 α \alpha α的值( 这点普通方法也可以很容易做到),还可以估计 α \alpha α的accuracy也就是其Standard Error。这可是只利用原有的样本进行一次估计所做不到的。那么Bootstrap对于分布特性的估计效果究竟如何呢?请看下图:

左边是真实的 α \alpha α,右边则是基于bootstrap方法得到的1000个 α \alpha α的分布,可以看到,二者是比较相近的,也就是说Bootstrap有着不错的估计效果。而且当重复次数增多,Bootstrap的估计效果会更好。
不仅是 α \alpha α的标准差,如果我们想要估计 α \alpha α的中位数、分位数等统计量,也是可以通过Boostrap方法做到的。

本质上,Bootstrap 方法,是将一次的估计过程,重复上千次上万次,从而便得到了得到上千个甚至上万个的估计值,于是利用这不止一个的估计值,我们就可以估计 α \alpha α均值以外的其他统计量:比如标准差、中位数等。

代码实现解决案例中的问题

数据集: 共 100 条数据

导入包和数据

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('Bootstrap.csv')
df.head(3) # 取前 3 条数据

用传统方法估计 X 总体均值和方差

#普通统计方法估计总体均值和方差
sample_mean = np.mean(df.X)
print("population mean is ",sample_mean )
sample_variance = np.var(df.X)
print("population variance is ",sample_variance/len(df.X ))

Bootstrap估计 X 总体均值和方差:

# 有放回的抽样一次后计算均值代码示例
from random import choices
index = np.random.choice(range(100),100) # 从 1 - 100 个数据中,随机选取,共选 100 个
np.mean(df.X[index])
sample_mean_list = [] # 存储每次抽样后的样本均值
for i in range(1000): # 共计又放回抽样 1000 次
    index = np.random.choice(range(100),100) # 每次抽样 100 个样本
    sample_mean_list.append(np.mean(df.X[index])) 
    
print("population mean is ",np.mean(sample_mean_list ))
population_variance = np.var(sample_mean_list)
print("population variance is ",population_variance)

# 通过柱状图展现 1000 次抽样结果
plt.hist(sample_mean_list)
plt.show()

解决案例中的选择 α \alpha α 来最小化 V a r ( α X + ( 1 − α ) X ) Var(\alpha X + (1 - \alpha) X) Var(αX+(1α)X)

# 用公式定义求解 alpha 的函数
def alpha_hat(data):
    x = data.X 
    y = data.Y
    covariance = np.cov(x,y)[0][1] # 计算 x 与 y 的协方差
    var_x =np.var(x) # 计算 x 的方差
    var_y =np.var(y) # 计算 y 的方差
    return (var_x-covariance)/(var_y+var_x-2*covariance)

执行 Bootstrap 方法进行抽样,获得最终结果

sample_mean_list = []
for i in range(100):
    index = np.random.choice(range(100),100)
    sample_mean_list.append(alpha_hat(df.iloc[index,:]))

print("The optimal alpha is: ",np.mean(sample_mean_list))
print("The variance of alpha is ",np.var(sample_mean_list))
plt.hist(sample_mean_list)

References

[1] 统计学中的Bootstrap方法(Bootstrap抽样)

[2] 统计学中的Bootstrap方法介绍及其应用

[3] 『迷你教程』机器学习的Bootstrap及Python实现

[4] 机器学习:Bootstrap

[5] 【机器学习】Bootstrap详解

  • 6
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值