单因素方差分析样例和代码 (One-Way ANOVA)

最近在研究线性回归分析中如何评估一个模型能否较好的描述数据,除了正常评测预测值和观测值的总体偏差(也是我们优化方向),我们还会对预测值和观测值偏差分布进行分析。这里具体的原因是: 正常在进行回归分析时,我们都会设置一个系统噪声,我们一般会有一下假设[1]:

  • 噪声与应变量 (response variable) 互相独立
  • 噪声信号服从正太分布(mean = 0, var = 小值)
  • 噪声在不同样本分类中的分布相同,并且服从正太分布(normal distribution)

那么正常在得出我们模型的预测值和观测值偏差分布时,我们希望验证一下我们建立模型时的假设还是否成立,这时候我们将应用到单因素方差分析(One-way ANOVA), 这里的单因素是指单个影响因素,一般指自变量,既然有单因素,是不是有多因素?答案是有的(Two-Way ANOVA & MANOVA), 多因素已超本篇内容,感兴趣的同学可以自己查阅相关资料。这里单因素方差分析主要目的是为了验证不同自变量分类中的应变量偏差的均值是否相同, 普遍的假设是多组偏差分布的均值相同(与t-test 的差异在于,t-test 一般用来对比两组样本)。

以下内容将分为三个部分,第一部分是单因素分析的理论部分,第二部分为具体样例分析,第三部分为样例代码

理论部分

既然单因素方差分析研究的是不同组内,因变量方差的均值是否相同,那么这里我们假设自变量( Ii ),即共有n组,每组中对应的应变量为( xij ), 该变量表示i组中j样本的值, 那么在单因素方差分析中,我们关心一下值:

  • 组内样本平均值 meani=1mj=0,mIij
  • 全局的平均值 grand_mean=1nmi=0,n;j=0,mIij
  • 组间自由度为 n - 1, 组内自由度胃n* (m- 1)
  • 组间方差 i=0,nm(meanigrand_mean)2 , 组间均方差 MSb=1n1i=0,n(meanigrand_mean)2
  • 组内方差 i=0,n;j=0,m(Ii,jmeani)2 , 组内均方差 MSw=1n(m1)i=0,n;j=0,m(Ii,jmeani)2
  • 组间均方差与组内均方差的比值 MSbMSw 为服从F(n, n * (m-1))分布的变量

当我们的significant值为 0.05时,我们有一个在自由度为(n, n* (m-1))下F的预期值 Fexpected , 和根据观测值计算的值 Fpractical , 当 Fexpected<Fpractical , 我们知道小概率时间放生,我们放弃原假设 null hypothesis

具体样例分析

这个case来于wiki [1], 这里将他重新整理, 自变量组为3,每组内的观测值为6,具体值见下表

I1 I2 I3
6 8 13
8 12 9
4 9 11
5 11 8
3 6 7
4 8 12

组内均值

I1 I2 I3
5 9 10
  • 全局均值 8,
  • 组间方差 Sb=6(58)2+6(98)2+6(108)2=84
  • 组间均方差 MSb=Sb/(n1)=84/(31)=42
  • 组内均方差 MSw=Sw/(n(m1))=68/(2(61))4.5
  • Fratio=SbSw9.3

上面是基于观测值计算的 Fratio , 接下来我们要基于观测值的自由度,计算对应的期望F 值,python 有对应的公开包可以计算(scipy.stats.f [2]), F(0.05,2,15)expected=3.68 , 观测值小于预期的F值,我们reject原假设

样例代码部分

# -*- encoding: utf-8 -*-
import re
import sys
import numpy as np
from scipy.stats import f

def main(instance):
    """
    """
    alpha = 0.05
    group_num = len(instance)
    ingroup_num = len(instance[0])
    group_mean = [np.mean(ele) for ele in instance]
    grand_mean = np.mean(group_mean)
    bg_squared_difference = sum([ingroup_num * ((ele - grand_mean) ** 2) for ele in group_mean])
    bg_degree = group_num - 1
    bg_mean_square = bg_squared_difference / bg_degree

    within_group_square = 0
    for i in range(group_num):
        for j in range(ingroup_num):
            within_group_square += (instance[i][j] - group_mean[i]) ** 2

    within_group_degree = group_num * (ingroup_num - 1)

    within_group_difference = within_group_square / within_group_degree

    F_practical = bg_mean_square / within_group_difference
    F_expected = f.ppf(alpha, bg_degree, within_group_degree)

    if F_practical > F_expected: return False

    return True

if __name__ == "__main__":
    reload(sys)
    sys.setdefaultencoding("utf-8")

    instance = [[6, 8, 4, 5, 3, 4],
                [8, 12, 9, 11, 6, 8],
                [13, 9, 11, 8, 7, 12]]
    print main(instance)

你可能感兴趣的:(数据分析相关代码)