bootstrap#
- scipy.stats.bootstrap(data, statistic, *, n_resamples=9999, batch=None, vectorized=None, paired=False, axis=0, confidence_level=0.95, alternative='two-sided', method='BCa', bootstrap_result=None, random_state=None)[源代码]#
计算统计量的双侧自举置信区间。
当 method 为
'percentile'
且 alternative 为'two-sided'
时,将根据以下过程计算自举置信区间。对数据进行重采样:对于 data 中的每个样本以及 n_resamples 中的每一个,从原始样本中随机抽取一个大小与原始样本相同的新样本(允许重复)。
计算统计量的自举分布:对于每组重采样,计算检验统计量。
确定置信区间:找到自举分布的区间,该区间
关于中位数对称,且
包含 confidence_level 的重采样统计量值。
虽然
'percentile'
方法是最直观的,但在实践中很少使用。还有两种更常用的方法,'basic'
(“反向百分位数”)和'BCa'
(“偏差校正和加速”);它们在执行步骤 3 的方式上有所不同。如果从各自的分布中随机抽取 data 中的样本 \(n\) 次,则
bootstrap
返回的置信区间将包含这些分布的统计量的真实值大约 confidence_level\(\, \times \, n\) 次。- 参数:
- data类数组序列
data 的每个元素都是一个样本,其中包含来自基础分布的标量观测值。 data 的元素必须可以广播到相同的形状(由 axis 指定的维度除外)。
- statistic可调用对象
要为其计算置信区间的统计量。 statistic 必须是一个可调用对象,它接受
len(data)
个样本作为单独的参数并返回结果统计量。如果 vectorized 设置为True
,statistic 还必须接受关键字参数 axis,并进行向量化以沿着提供的 axis 计算统计量。- n_resamples整数,默认值:
9999
为形成统计量的自举分布而执行的重采样次数。
- batch整数,可选
在每次向量化调用 statistic 时要处理的重采样次数。内存使用量为 O( batch *
n
),其中n
是样本大小。默认值为None
,在这种情况下batch = n_resamples
(或者对于method='BCa'
,batch = max(n_resamples, n)
)。- vectorized布尔值,可选
如果 vectorized 设置为
False
,则不会将关键字参数 axis 传递给 statistic,并且预计只计算一维样本的统计量。如果为True
,则会将关键字参数 axis 传递给 statistic,并且预计在传递 ND 样本数组时,它会沿着 axis 计算统计量。如果为None
(默认值),如果axis
是 statistic 的参数,则 vectorized 将设置为True
。使用向量化统计量通常可以减少计算时间。- paired布尔值,默认值:
False
统计量是否将 data 中样本的对应元素视为配对。
- axis整数,默认值:
0
data 中样本的轴,沿着该轴计算 statistic。
- confidence_level浮点数,默认值:
0.95
置信区间的置信水平。
- alternative{‘two-sided’, ‘less’, ‘greater’},默认值:
'two-sided'
选择
'two-sided'
(默认值)表示双侧置信区间,选择'less'
表示下限为-np.inf
的单侧置信区间,选择'greater'
表示上限为np.inf
的单侧置信区间。单侧置信区间的另一侧界限与 confidence_level 距离 1.0 两倍的双侧置信区间的界限相同;例如,95%'less'
置信区间的上限与 90%'two-sided'
置信区间的上限相同。- method{‘percentile’, ‘basic’, ‘bca’},默认值:
'BCa'
是返回“百分位数”自举置信区间 (
'percentile'
),“基本”(又称“反向”)自举置信区间 ('basic'
),还是偏差校正和加速自举置信区间 ('BCa'
)。- bootstrap_resultBootstrapResult,可选
提供先前调用
bootstrap
返回的结果对象,以将先前的自举分布包含在新自举分布中。例如,这可用于更改 confidence_level、更改 method 或查看执行其他重采样而不重复计算的效果。- random_state{None, int,
numpy.random.Generator
, 用于生成重采样的伪随机数生成器状态。
如果 random_state 为
None
(或 np.random),则使用numpy.random.RandomState
单例。如果 random_state 是一个整数,则使用一个新的RandomState
实例,并使用 random_state 作为种子。如果 random_state 已经是一个Generator
或RandomState
实例,则使用该实例。
- 返回值:
- resBootstrapResult
具有以下属性的对象
- confidence_intervalConfidenceInterval
自举置信区间,作为
collections.namedtuple
的实例,具有 low 和 high 属性。- bootstrap_distributionndarray
bootstrap 分布,即每次重采样的 statistic 值。最后一个维度对应于重采样(例如
res.bootstrap_distribution.shape[-1] == n_resamples
)。- standard_errorfloat 或 ndarray
bootstrap 标准误差,即 bootstrap 分布的样本标准偏差。
- 警告:
DegenerateDataWarning
当
method='BCa'
且 bootstrap 分布退化(例如,所有元素都相同)时生成。
注意
如果 bootstrap 分布退化(例如,所有元素都相同),则对于
method='BCa'
,置信区间的元素可能为 NaN。在这种情况下,请考虑使用其他 method 或检查 data 以指示其他分析可能更合适(例如,所有观察值都相同)。参考文献
[1]B. Efron and R. J. Tibshirani, An Introduction to the Bootstrap, Chapman & Hall/CRC, Boca Raton, FL, USA (1993)
[2]Nathaniel E. Helwig,“Bootstrap Confidence Intervals”,http://users.stat.umn.edu/~helwig/notes/bootci-Notes.pdf
[3]Bootstrapping (统计),维基百科,https://en.wikipedia.org/wiki/Bootstrapping_%28statistics%29
示例
假设我们从未知分布中抽样数据。
>>> import numpy as np >>> rng = np.random.default_rng() >>> from scipy.stats import norm >>> dist = norm(loc=2, scale=4) # our "unknown" distribution >>> data = dist.rvs(size=100, random_state=rng)
我们对分布的标准差感兴趣。
>>> std_true = dist.std() # the true value of the statistic >>> print(std_true) 4.0 >>> std_sample = np.std(data) # the sample statistic >>> print(std_sample) 3.9460644295563863
bootstrap 用于近似如果我们重复从未知分布中抽样并每次计算样本的统计量时所期望的变化性。它通过重复地从原始样本中进行有放回的重采样并计算每次重采样的统计量来实现这一点。这导致统计量的“bootstrap 分布”。
>>> import matplotlib.pyplot as plt >>> from scipy.stats import bootstrap >>> data = (data,) # samples must be in a sequence >>> res = bootstrap(data, np.std, confidence_level=0.9, ... random_state=rng) >>> fig, ax = plt.subplots() >>> ax.hist(res.bootstrap_distribution, bins=25) >>> ax.set_title('Bootstrap Distribution') >>> ax.set_xlabel('statistic value') >>> ax.set_ylabel('frequency') >>> plt.show()
标准误差量化了这种变化性。它被计算为 bootstrap 分布的标准差。
>>> res.standard_error 0.24427002125829136 >>> res.standard_error == np.std(res.bootstrap_distribution, ddof=1) True
统计量的 bootstrap 分布通常近似正态分布,其尺度等于标准误差。
>>> x = np.linspace(3, 5) >>> pdf = norm.pdf(x, loc=std_sample, scale=res.standard_error) >>> fig, ax = plt.subplots() >>> ax.hist(res.bootstrap_distribution, bins=25, density=True) >>> ax.plot(x, pdf) >>> ax.set_title('Normal Approximation of the Bootstrap Distribution') >>> ax.set_xlabel('statistic value') >>> ax.set_ylabel('pdf') >>> plt.show()
这表明我们可以根据此正态分布的分位数构建统计量的 90% 置信区间。
>>> norm.interval(0.9, loc=std_sample, scale=res.standard_error) (3.5442759991341726, 4.3478528599786)
由于中心极限定理,这种正态近似对于各种统计量和样本的潜在分布都是准确的;然而,这种近似并非在所有情况下都是可靠的。因为
bootstrap
旨在处理任意的潜在分布和统计量,所以它使用更先进的技术来生成准确的置信区间。>>> print(res.confidence_interval) ConfidenceInterval(low=3.57655333533867, high=4.382043696342881)
如果我们从原始分布中抽样 100 次并为每个样本形成一个 bootstrap 置信区间,则置信区间大约 90% 的时间包含统计量的真实值。
>>> n_trials = 100 >>> ci_contains_true_std = 0 >>> for i in range(n_trials): ... data = (dist.rvs(size=100, random_state=rng),) ... res = bootstrap(data, np.std, confidence_level=0.9, ... n_resamples=999, random_state=rng) ... ci = res.confidence_interval ... if ci[0] < std_true < ci[1]: ... ci_contains_true_std += 1 >>> print(ci_contains_true_std) 88
我们也可以一次性确定所有 100 个样本的置信区间,而不是编写循环。
>>> data = (dist.rvs(size=(n_trials, 100), random_state=rng),) >>> res = bootstrap(data, np.std, axis=-1, confidence_level=0.9, ... n_resamples=999, random_state=rng) >>> ci_l, ci_u = res.confidence_interval
在这里,ci_l 和 ci_u 包含
n_trials = 100
个样本中每一个的置信区间。>>> print(ci_l[:5]) [3.86401283 3.33304394 3.52474647 3.54160981 3.80569252] >>> print(ci_u[:5]) [4.80217409 4.18143252 4.39734707 4.37549713 4.72843584]
同样,大约 90% 包含真实值
std_true = 4
。>>> print(np.sum((ci_l < std_true) & (std_true < ci_u))) 93
bootstrap
还可以用于估计多样本统计量的置信区间。例如,要获得均值之差的置信区间,我们编写一个函数,该函数接受两个样本参数并仅返回统计量。使用axis
参数可确保所有均值计算都在单个向量化调用中执行,这比在 Python 中循环遍历重采样对要快。>>> def my_statistic(sample1, sample2, axis=-1): ... mean1 = np.mean(sample1, axis=axis) ... mean2 = np.mean(sample2, axis=axis) ... return mean1 - mean2
在这里,我们使用默认置信水平为 95% 的“百分位数”方法。
>>> sample1 = norm.rvs(scale=1, size=100, random_state=rng) >>> sample2 = norm.rvs(scale=2, size=100, random_state=rng) >>> data = (sample1, sample2) >>> res = bootstrap(data, my_statistic, method='basic', random_state=rng) >>> print(my_statistic(sample1, sample2)) 0.16661030792089523 >>> print(res.confidence_interval) ConfidenceInterval(low=-0.29087973240818693, high=0.6371338699912273)
标准误差的 bootstrap 估计值也可用。
>>> print(res.standard_error) 0.238323948262459
配对样本统计量也可以使用。例如,考虑 Pearson 相关系数。
>>> from scipy.stats import pearsonr >>> n = 100 >>> x = np.linspace(0, 10, n) >>> y = x + rng.uniform(size=n) >>> print(pearsonr(x, y)[0]) # element 0 is the statistic 0.9954306665125647
我们包装了
pearsonr
,以便它只返回统计量,确保我们使用了 axis 参数,因为它可用。>>> def my_statistic(x, y, axis=-1): ... return pearsonr(x, y, axis=axis)[0]
我们使用
paired=True
调用bootstrap
。>>> res = bootstrap((x, y), my_statistic, paired=True, random_state=rng) >>> print(res.confidence_interval) ConfidenceInterval(low=0.9941504301315878, high=0.996377412215445)
结果对象可以传递回
bootstrap
以执行额外的重采样>>> len(res.bootstrap_distribution) 9999 >>> res = bootstrap((x, y), my_statistic, paired=True, ... n_resamples=1000, random_state=rng, ... bootstrap_result=res) >>> len(res.bootstrap_distribution) 10999
或更改置信区间选项
>>> res2 = bootstrap((x, y), my_statistic, paired=True, ... n_resamples=0, random_state=rng, bootstrap_result=res, ... method='percentile', confidence_level=0.9) >>> np.testing.assert_equal(res2.bootstrap_distribution, ... res.bootstrap_distribution) >>> res.confidence_interval ConfidenceInterval(low=0.9941574828235082, high=0.9963781698210212)
而无需重复计算原始 bootstrap 分布。