permutation_test: 用于假设检验的置换检验
假设检验的置换检验实现 -- 检验两个不同组来自相同分布的零假设。
from mlxtend.evaluate import permutation_test
概述
置换检验(也称为精确检验、随机化检验或再随机化检验)是一种非参数检验程序,用于检验两个不同组来自相同分布的零假设。置换检验可用于显著性检验或假设检验(包括 A/B 检验),而无需对抽样分布做出任何假设(例如,它不要求样本服从正态分布)。
在本文档中,我们将精确方法称为“置换检验”,近似方法称为“随机化检验”。
置换检验机制
在零假设(处理组 = 对照组)下,任何置换都具有同等可能性。(请注意,存在 (n+m)! 种置换,其中 n 是处理样本中的记录数,m 是对照样本中的记录数)。对于双侧检验,我们定义备择假设为两个样本不同(例如,处理组 != 对照组)。
- 计算样本 x 和样本 y 的差值(此处为均值)
- 将所有测量结果合并到一个单一数据集中
- 从步骤 2 中数据集的所有可能置换中抽取一个置换数据集。
- 将置换数据集分别划分为大小为 n 和 m 的两个数据集 x' 和 y'
- 计算样本 x' 和样本 y' 的差值(此处为均值)并记录该差值
- 重复步骤 3-5,直到评估所有置换
- 返回 p 值,即记录的差值至少与步骤 1 中的原始差值一样极端的次数,并将此次数除以总置换数
在此,p 值定义为在零假设(样本之间无差异)为真时,我们获得的结果至少与我们观察到的结果(即步骤 1 中的样本差值)一样极端的概率。
更正式地,我们可以将 p 值的计算表示如下(改编自 [2])
其中是检验统计量的观测值(即上面列表中的第 1 点),并且是 t 值,即根据重采样(第 5 点)计算出的统计量,且 I 是指示函数。
给定我们在进行置换检验之前指定的显著性水平(例如 alpha=0.05),如果 p 值大于 alpha,则我们无法拒绝零假设。
请注意,如果置换数量很大,计算上可能无法对所有置换进行采样。因此,一种常见的近似方法是执行 k 轮置换(其中 k 通常在 1000 到 2000 之间)。
配对样本
通过设置 paired=True
,置换(/随机化)检验也可以用于配对样本。配对检验与上述常规置换检验程序类似,不同之处在于置换样本是通过在每对内部随机交换一个处理数据点和一个对照数据点来创建的。
参考文献
- [1] Efron, Bradley and Tibshirani, R. J., An introduction to the bootstrap, Chapman & Hall/CRC Monographs on Statistics & Applied Probability, 1994.
- [2] Unpingco, José. Python for probability, statistics, and machine learning. Springer, 2016.
- [3] Pitman, E. J. G., Significance tests which may be applied to samples from any population, Royal Statistical Society Supplement, 1937, 4: 119-30 and 225-32
示例 1 -- 双侧随机化检验
执行双侧随机化检验,以检验“处理组”和“对照组”两个组来自相同分布的零假设。我们将 alpha=0.01 指定为显著性水平。
treatment = [ 28.44, 29.32, 31.22, 29.58, 30.34, 28.76, 29.21, 30.4 ,
31.12, 31.78, 27.58, 31.57, 30.73, 30.43, 30.31, 30.32,
29.18, 29.52, 29.22, 30.56]
control = [ 33.51, 30.63, 32.38, 32.52, 29.41, 30.93, 49.78, 28.96,
35.77, 31.42, 30.76, 30.6 , 23.64, 30.54, 47.78, 31.98,
34.52, 32.42, 31.32, 40.72]
由于评估所有可能的置换可能需要一些时间,我们将使用近似方法(详见引言),即随机化检验
from mlxtend.evaluate import permutation_test
p_value = permutation_test(treatment, control,
method='approximate',
num_rounds=10000,
seed=0)
print(p_value)
0.0066993300669933005
由于 p 值 < alpha,我们可以拒绝两个样本来自相同分布的零假设。
示例 2 -- 用于计算相关分析 (Pearson's R) p 值的置换检验
注意:这是一项单侧假设检验,因为我们进行的置换检验是“有多少次获得的关联系数大于观测值?”
import numpy as np
from mlxtend.evaluate import permutation_test
x = np.array([1, 2, 3, 4, 5, 6])
y = np.array([2, 4, 1, 5, 6, 7])
print('Observed pearson R: %.2f' % np.corrcoef(x, y)[1][0])
p_value = permutation_test(x, y,
method='exact',
func=lambda x, y: np.corrcoef(x, y)[1][0],
seed=0)
print('P value: %.2f' % p_value)
Observed pearson R: 0.81
P value: 0.10
示例 3 -- 配对两样本随机化检验
假设我们有一个数据集,包含威斯康星州七个湖泊的深度(米)
我们感兴趣的是检验零假设:1980 年和 1990 年湖泊的深度没有显著差异。对于这个配对双样本检验,我们在 0.05 的显著性水平下进行配对样本的随机化检验
from mlxtend.evaluate import permutation_test
lakes_1980 = [3.67, 1.72, 3.46, 2.60, 2.03, 2.10, 3.01]
lakes_1990 = [2.11, 1.79, 2.71, 1.89, 1.69, 1.71, 2.01]
p_value = permutation_test(
lakes_1980, lakes_1990, paired=True, method="approximate", seed=0, num_rounds=100000
)
print('P value: %.3f' % p_value)
P value: 0.031
由于 p 值小于显著性阈值 0.05,我们得出结论:1980 年和 1990 年湖泊深度之间存在显著差异。
API
permutation_test(x, y, func='x_mean != y_mean', method='exact', num_rounds=1000, seed=None, paired=False)
非参数置换检验
参数
-
x
: 列表或 numpy 数组,形状为 (n_datapoints,)第一个样本的列表或 1D numpy 数组(例如,处理组)。
-
y
: 列表或 numpy 数组,形状为 (n_datapoints,)第二个样本的列表或 1D numpy 数组(例如,对照组)。
-
func
: 自定义函数或字符串(默认值:'x_mean != y_mean')用于计算置换检验统计量的函数。 - 如果是 'x_mean != y_mean',则使用
func=lambda x, y: np.abs(np.mean(x) - np.mean(y)))
进行双侧检验。 - 如果是 'x_mean > y_mean',则使用func=lambda x, y: np.mean(x) - np.mean(y))
进行单侧检验。 - 如果是 'x_mean < y_mean',则使用func=lambda x, y: np.mean(y) - np.mean(x))
进行单侧检验。 -
method
: 'approximate' 或 'exact'(默认值:'exact')如果为 'exact'(默认值),则考虑所有可能的置换。如果为 'approximate',则抽样次数由
num_rounds
指定。请注意,除非数据集大小相对较小,否则 'exact' 方法通常不可行。 -
paired
: 布尔值如果为 True,则仅通过交换每个数据点与其配对的数据点来执行配对检验。
-
num_rounds
: 整型(默认值:1000)如果
method='approximate'
,则为置换样本的数量。 -
seed
: 整型或 None(默认值:None)如果
method='approximate'
,则为生成置换样本的随机种子。
返回值
零假设下的 p 值 示例
用法示例请参阅 https://mlxtend.cn/mlxtend/user_guide/evaluate/permutation_test/