假设检验

假设检验概览

在总体分布函数完全未知,或者只知其形式、但不知道其参数的情况下,为了推断总体的某些未知的特性,提出的关于总体的假设。

算法流程

假设检验的算法流程如下:

  1. 确定显著性水平
  2. 确定原假设
  3. 确定备选假设
  4. 确定检验统计量
  5. 使用样本数据计算检验统计量的值
  6. 计算检验统计量发生的概率
  7. 对比发生的概率和显著性水平,确定是否拒绝原假设。

在实际使用的过程中,因为步骤6是需要根据统计量分布计算的,如使用计算机计算,或者查表比较麻烦,而步骤5可以直接根据样本数据计算。所以实际中步骤5、6、7会做如下修改:

  1. 根据统计量分布和显著性水平计算拒绝原假设的临界值,确定拒绝域和接受域
  2. 使用样本数据计算检验检验统计量的值
  3. 根据检测统计量的值在拒绝域或接受域内来决定是否拒绝原假设。

假设检验的难点主要是指在步骤2和步骤4。在学习假设检验之前,参照附录一先理解一下p_value。

定义
第一类错误:原假设为真,结果拒绝了原假设。
第二类错误:原假设为假,结果接受了原假设。

如何确定原假设

假设检验中,一般情况下原假设是为了实现目标,在基于先验知识的情况下做出的假设,所以假设检验算法本身是倾向于接受原假设的,只有数据给的理由足够充分,才会拒绝原假设。基于这一点,有以下结论:

结论一:如果原假设没有设定好,原假设本身是错的,数据量又不够的情况下,检测结果会比较容易犯第二类错误(附录二)。在数据量已定的情况下,为了使得整个假设检验更有意义,需要根据原理来设置合理的原假设。

结论二:如果数据量很少的话,并没有太大的意义做假设检验。假设检验的结果很容易犯错(附录二)。

结论三:当数据量比较大的时候,需要设定更大的显著水平。否则,只要真实结果与原假设有一点点差,就很容易拒绝原假设(附录三)。

结论四:扩大数据量能够降低犯第二类错误的概率。换个角度,为了控制第二类错误的概率,需要更多的数据量。(多大的数据量是合适的,就引申出功效函数

确定检验统计量

假设检验结果是根据p_value值来判断的。p_value值,也是一个概率值。概率值常见两种计算方式,一种是使用频率估计概率,一种是基于数据分布函数计算得到。假设检验是检验判断对错的概率,如果使用频率估计概率的思想,就需要相同事件出现很多次,每次判断后得到反馈结果,然后基于判断正确的频率来估计概率,而这在实际中是不现实的。所以假设检验中的p_value是通过数据分布函数计算得到的。

假设检验需要分布函数,那么就需要构造满足某种分布的统计量。而该统计量的值基于样本数据和假设条件计算得到。

不同的数据分布前提,不同的实际情况下,有不同的数据分布。可以从不同的角度构造统计量。统计量有好坏之分,可以基于统计量的无偏性、有效性、相合性等来比较统计量的优劣。

构造统计量一般情况下还有一个前提:尽可能的利用已知的先验知识。在数据量已定的前提下,利用了更多的先验知识,更容易拒绝原假设。能在不提高犯第一列错误的前提下,降低犯第二类错误的概率(附录四)。

在假设检验中,正态总体的假设检验是比较多用的(附录五)。

假设检验案例

基础知识(p142)
定理一: 独立同正态分布的n个随机变量的和还是正态分布。

定理二: 独立同正态分布的n个随机变量的均值和方差相互独立,且方差服从自由度为n-1的卡方分布

定理三: 独立同正态分布的n个随机变量的均值与标准差可以构造t分布。(直接由t分布的定义和定理一、定理二得到)

定理四: 一组独立同正态分布的m个随机变量的方差与另一组独立同正态分布的n个随机变量的方差可以构造F分布。(由定理二和F分布的定义直接得到);一组独立同正态分布的m个随机变量的均值、方差与另一组独立同正态分布的n个随机变量的均值、方差,当方差相等时,可以构造t分布。由定理一、定理二和t分布的定义可以得到。

  • 基于定理一,可以做方差已知的关于均值的显著性检验;
  • 基于定理二,可以做方差未知的关于均值的显著性检验;
  • 基于定理四,可以做方差相同的两正态总体的均值差的显著性检验;
  • 基于定理二,可以做正态总体的方差的显著性检验;
  • 基于定理四,可以做两正态总体的方差是否有差异的显著性检验;

附录

函数准备

import numpy as np
from scipy import stats

def z_test(X, t_mean=0, std=1, test_type='both', is_print=True):
    """Z检验
    
    总体方差已知情况下,正态分布总体的均值的检验
    
    Parameters
    ----------
    X: list or np.array, 样本数据
    t_mean: float, 检测均值
    std: float, 总体方差
    test_type: 检测类型,双边检验/左侧单边检验/右侧单边检验
    
    Return
    ------
    float, p_value值
    """
    n = len(X)
    T = np.sqrt(n) * (np.mean(X) - t_mean) / std
    if test_type == 'both':
        p_value = 2 * (1 - stats.norm.cdf(np.abs(T))) # 正态分布就是在这里用到的
    elif test_type == 'right':
        p_value = stats.norm.cdf(T)
    else:
        p_value = 1 - stats.norm.cdf(T)
    if is_print:
        print('t_mean:{}, std:{}, test_type:{} | p_value:{:.5}'.format(
            t_mean, std, test_type, p_value))
    return p_value

def t_test(X, t_mean=0, test_type='both', is_print=True):
    """t检验
    
    总体方差未知情况下,正态分布总体的均值的检验
    
    Parameters
    ----------
    X: list or np.array, 样本数据
    t_mean: float, 检测均值
    test_type: 检测类型,双边检验/左侧单边检验/右侧单边检验
    
    Return
    ------
    float, p_value值
    """
    n = len(X)
    T = (np.mean(X) - t_mean) / (np.std(X) / np.sqrt(n-1))
    if test_type == 'both':
        p_value = 2 * (1 - stats.t.cdf(np.abs(T), n-1)) # t分布就是在这里用到的 
    elif test_type == 'right':
        p_value = stats.t.cdf(T, n-1)
    else:
        p_value = 1 - stats.t.cdf(T, n-1)
    if is_print:
        print('t_mean:{}, test_type:{} | p_value:{:.5}'.format(
            t_mean, test_type, p_value))
    return p_value

附录一

假设数据取自同一个分布,使用相同的显著水平,相同的检测方法做检验。

for i in range(5):
    _ = z_test(np.random.normal(0, 1, 100), t_mean=0, std=1, is_print=True)

结果如下:
t_mean:0, std:1, test_type:both | p_value:0.83079
t_mean:0, std:1, test_type:both | p_value:0.042919
t_mean:0, std:1, test_type:both | p_value:0.25172
t_mean:0, std:1, test_type:both | p_value:0.80495
t_mean:0, std:1, test_type:both | p_value:0.91295

每次的检验结果是可能不同的,对比理解p_value的含义。对比不同的次数下p_value的表现。

n = 5
p_value = [np.mean([z_test(np.random.normal(0, 1, 100), t_mean=0, std=1, is_print=False) for i in range(n)]) for j in range(10)]
print('n={}, p_value_mean={:.3}, p_value_var={:.3}'.format(n, np.mean(p_value), np.var(p_value)))
n = 10
p_value = [np.mean([z_test(np.random.normal(0, 1, 100), t_mean=0, std=1, is_print=False) for i in range(n)]) for j in range(10)]
print('n={}, p_value_mean={:.3}, p_value_var={:.3}'.format(n, np.mean(p_value), np.var(p_value)))
n = 20
p_value = [np.mean([z_test(np.random.normal(0, 1, 100), t_mean=0, std=1, is_print=False) for i in range(n)]) for j in range(10)]
print('n={}, p_value_mean={:.3}, p_value_var={:.3}'.format(n, np.mean(p_value), np.var(p_value)))

结果如下:
n=5, p_value_mean=0.48, p_value_var=0.0157
n=10, p_value_mean=0.504, p_value_var=0.00723
n=20, p_value_mean=0.499, p_value_var=0.00193

当相同情况做的次数多了以后,检测的p_value的均值是越来越稳定的。之后的对比不同检验情况下p_value的差异的时候设置n为100。

附录二

样本取自相同的总体分布,假设总体分布为标准正态分布 N ( 0 , 1 ) N(0,1) N(0,1)。对比相同的数据量下,Z检验对关于均值为0和均值为0.1的检测结果。

sample_num = 10
t_mean = 0
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=t_mean, std=1, is_print=False) for i in range(100)])
print('sample num:{}, t_mean:{}, p_value={}'.format(sample_num, t_mean, p_value))
t_mean = 0.1
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=t_mean, std=1, is_print=False) for i in range(100)])
print('sample num:{}, t_mean:{}, p_value={}'.format(sample_num, t_mean, p_value))

sample_num = 100
t_mean = 0
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=t_mean, std=1, is_print=False) for i in range(100)])
print('sample num:{}, t_mean:{}, p_value={}'.format(sample_num, t_mean, p_value))
t_mean = 0.1
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=t_mean, std=1, is_print=False) for i in range(100)])
print('sample num:{}, t_mean:{}, p_value={}'.format(sample_num, t_mean, p_value))

sample_num = 1000
t_mean = 0
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=t_mean, std=1, is_print=False) for i in range(100)])
print('sample num:{}, t_mean:{}, p_value={}'.format(sample_num, t_mean, p_value))
t_mean = 0.1
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=t_mean, std=1, is_print=False) for i in range(100)])
print('sample num:{}, t_mean:{}, p_value={}'.format(sample_num, t_mean, p_value))

结果如下:
sample num:10, t_mean:0, p_value=0.5072029252323097
sample num:10, t_mean:0.1, p_value=0.46138045248769893
sample num:100, t_mean:0, p_value=0.4875769624054251
sample num:100, t_mean:0.1, p_value=0.4245074008824946
sample num:1000, t_mean:0, p_value=0.4773629769262692
sample num:1000, t_mean:0.1, p_value=0.023915295736835533

对比不同的样本数量下,不同的均值的检测结果

sample_num = 10
t_mean = 0
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=t_mean, std=1, is_print=False) for i in range(100)])
print('sample num:{}, t_mean:{}, p_value={}'.format(sample_num, t_mean, p_value))
t_mean = 0.5
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=t_mean, std=1, is_print=False) for i in range(100)])
print('sample num:{}, t_mean:{}, p_value={}'.format(sample_num, t_mean, p_value))

sample_num = 5
t_mean = 0
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=t_mean, std=1, is_print=False) for i in range(100)])
print('sample num:{}, t_mean:{}, p_value={}'.format(sample_num, t_mean, p_value))
t_mean = 1
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=t_mean, std=1, is_print=False) for i in range(100)])
print('sample num:{}, t_mean:{}, p_value={}'.format(sample_num, t_mean, p_value))

结果如下:
sample num:10, t_mean:0, p_value=0.47722880090175634
sample num:10, t_mean:0.5, p_value=0.23667633388385417
sample num:5, t_mean:0, p_value=0.5310308791352258
sample num:5, t_mean:1, p_value=0.11377033525596417

附录三

样本取自相同的总体分布,假设总体分布为标准正态分布 N ( 0 , 1 ) N(0,1) N(0,1)。对比不同的数据量的情况下,z检验对关于均值为0.1的检测结果差异。

sample_num = 10
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=0.1, std=1, is_print=False) for i in range(100)])
print('sample num:{}, p_value={}'.format(sample_num, p_value))
sample_num = 100
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=0.1, std=1, is_print=False) for i in range(100)])
print('sample num:{}, p_value={}'.format(sample_num, p_value))
sample_num = 1000
p_value = np.mean([z_test(np.random.normal(0, 1, sample_num), t_mean=0.1, std=1, is_print=False) for i in range(100)])
print('sample num:{}, p_value={}'.format(sample_num, p_value))

结果如下:
sample num:10, p_value=0.4848865002720213
sample num:100, p_value=0.3826647304964832
sample num:1000, p_value=0.026368291730919216

样本量越多,检测结果越容易拒绝原假设。

附录四

在样本量已定的前提下。当总体方差已知的前提下,对比t_test和z_test的检测结果。

sample_num = 10
t_p_value = []
z_p_value = []
for j in range(1000):
    X = np.random.normal(0, 0.5, sample_num)
    t_p_value.append(t_test(X, t_mean=0.2, is_print=False))
    z_p_value.append(z_test(X, t_mean=0.2, std=0.5, is_print=False))
t_p_value = np.mean(t_p_value)
z_p_value = np.mean(z_p_value)
print('sample num:{}, t_p_value={}, z_p_value={}'.format(sample_num, t_p_value, z_p_value))

结果如下:
sample num:10, t_p_value=0.31059238958063545, z_p_value=0.30291339323045574

当总体方差已知的前提下,t_test和z_test都可以做正态总体均值的假设检验,但是因为z_test使用了总体方差的信息,一般情况下,当原假设出错的时候,z_test的p值会比较小。

附录五

中心极限定理:假设随机变量 X 1 , X 2 , . . . , X n X_1,X_2,...,X_n X1,X2,...,Xn相互独立,服从同一分布。且具有数学期望和方差: E ( X k ) = μ , D ( X k ) = σ 2 > 0 ( k = 1 , 2 , 3... ) E(X_k)= \mu,D(X_k)=\sigma^2>0(k=1,2,3...) E(Xk)=μ,D(Xk)=σ2>0(k=1,2,3...),则随机变量之和 ∑ k = 1 n X k \sum_{k=1}^nX_k k=1nXk的标准化变量
Y n = ∑ k = 1 n X k − E ( ∑ k = 1 n X k ) D ( ∑ k = 1 n X k ) = ∑ k = 1 n X k − n μ n σ Y_n={\sum_{k=1}^nX_k-E(\sum_{k=1}^nX_k) \over \sqrt {D(\sum_{k=1}^nX_k)}}={\sum_{k=1}^nX_k-n\mu \over \sqrt n\sigma} Yn=D(k=1nXk) k=1nXkE(k=1nXk)=n σk=1nXknμ
的分布函数 F n ( x ) F_n(x) Fn(x)对于任意x满足
lim ⁡ n → + ∞ F n ( x ) = lim ⁡ n → + ∞ P { ∑ k = 1 n X k − n μ n σ ≤ x } = ∫ − ∞ x 1 2 π e − t 2 / 2 d t = Φ ( x ) \lim\limits_{n \rightarrow +\infty}F_n(x)=\lim\limits_{n \rightarrow +\infty}P\{ {\sum_{k=1}^nX_k-n\mu \over \sqrt n\sigma}\leq x\}=\int_{-\infty}^x \frac{1}{\sqrt {2\pi}}e^{-t^2/2}{\rm d}t=\Phi(x) n+limFn(x)=n+limP{n σk=1nXknμx}=x2π 1et2/2dt=Φ(x)

# 总体数据为y
y = np.random.choice(list(range(100)), 1000)
# 样本数据为从总体y中独立抽取的50个数据并取均值,重复抽取100次
X = [np.mean(np.random.choice(y, 50)) for i in range(100)]
# 使用shapiro做X的正态性检验
# 为了得到更加可靠的数据,做50次检验取均值
p_value = np.mean([stats.shapiro([np.mean(np.random.choice(y, 50)) for i in range(100)])[1] for i in range(50)])
print('{:.5}'.format(p_value))

结果如下:
0.43548

检测结果发现,这样取出来的值服从正态分布,跟中心极限定理一致。因为每个X的均值的期望与等于总体y的均值。所以可以根据X的值来做总体y的均值的显著性检验。

很容易犯的一个错误是直接对从总体y中随机选择的数据做t检验。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值