ChiMerge算法:卡方检验+ChiMerge+Python

卡方分布与卡方检验

卡方分布

  • 定义
    • 若n个相互独立的随机变量 ξ 1 , ξ 2 , … , ξ n \xi_{1},\xi_{2},\dots,\xi_{n} ξ1,ξ2,,ξn均服从标准正态分布,则这n个服从标准正态分布的随机变量的平方和 Q = ∑ i = 1 n ξ i 2 Q=\sum_{i=1}^{n}\xi_{i}^{2} Q=i=1nξi2 构成一个新的随机变量,其分布规律称为 χ 2 \chi_{2} χ2分布(chi-square distribution),记为 Q Q Q满足自由度为 v v v χ 2 \chi_{2} χ2分布 Q ∼ χ 2 ( v ) Q \sim \chi^{2}(v) Qχ2(v) Q ∼ χ v 2 Q \sim \chi^{2}_{v} Qχv2(其中 v = n − k v=n-k v=nk k k k为限制条件数);
    • 卡方分布是由正态分布构造而成的一个新的分布,当自由度 v v v很大时,卡方分布近似为正态分布。
  • 概率密度函数
    • 概率密度函数
    • f ( x ; k ) = { x ( k / 2 ) − 1 e − x / 2 2 k / 2 Γ ( k 2 ) , x ≥ 0 0 ,  otherwise  f(x ; k)=\left\{\begin{array}{ll} \frac{x^{(k / 2)-1} e^{-x / 2}}{2^{k / 2} \Gamma\left(\frac{k}{2}\right)}, & x \geq 0 \\ 0, & \text { otherwise } \end{array}\right. f(x;k)={2k/2Γ(2k)x(k/2)1ex/2,0,x0 otherwise 
    • 其中, Γ ( k 2 ) \Gamma (\frac {k}{2}) Γ(2k)是伽玛函数;
    • 均值为自由度v,记为 E ( χ 2 ) = v E(\chi^{2})=v E(χ2)=v
    • 方差为2倍的自由度:2v,记为 D ( χ 2 = 2 v D(\chi^{2}=2v D(χ2=2v
  • 性质
    • χ 2 \chi_{2} χ2分布在第一象限内,卡方值都是正值,随着参数v的增大, χ 2 \chi_{2} χ2分布趋近于正态分布;
    • 卡方分布密度曲线下的面积都是1;
    • 随着自由度v的增大, χ 2 \chi_{2} χ2分布向正无穷方向延伸(因为均值v越来越大),分布曲线也越来越低阔(因为方差2v越来越大)。
    • 不同的自由度决定不同的卡方分布,自由度越小,分布越偏斜;自由度越大,该函数图像越对称;
    • χ 2 ( v 2 ) , χ 2 ( v 2 ) \chi_{2}(v_2),\chi_{2}(v_2) χ2(v2)χ2(v2)互相独立,则 χ 2 ( v 2 ) + χ 2 ( v 2 ) \chi_{2}(v_2)+\chi_{2}(v_2) χ2(v2)+χ2(v2)服从 χ 2 \chi_{2} χ2分布,自由度为 v 1 + v 2 v_1+v_2 v1+v2
  • OneMoreThing(有待商榷):"为什么这里 ξ \xi ξ需要正态分布,我的理解是,如果零假设为真,那么观测值和期望值之间的波动程度,应该是正态分布的,或者说“噪声”应该是正态分布的。"源自卡方检验详解

卡方 χ 2 \chi^{2} χ2检验

  • 基本原理:卡方检验就是统计样本的实际观测值与理论推断值之间的偏离程度,实际观测值与理论推断值之间的偏离程度就决定卡方值的大小,如果卡方值越大,二者偏差程度越大;反之,二者偏差越小;若两个值完全相等时,卡方值就为0,表明理论值完全符合。
  • 首先假设 H 0 H_0 H0(观察频数与期望频数没有差别)成立,基于此前提计算出 χ 2 \chi^{2} χ2值。如果 χ 2 \chi^{2} χ2值“小”,倾向于接受 H 0 H_0 H0;如果 χ 2 \chi^{2} χ2值大,就倾向于拒绝 H 0 H_0 H0。至于 χ 2 \chi^{2} χ2在每个具体研究中究竟要大到什么程度(置信度)才能拒绝 χ 2 \chi^{2} χ2,则要借助于卡方分布与自由度确定所对应的 P P P值。
  • χ 2 \chi^{2} χ2值计算
    • 设A代表某个类别的观察频数,E代表基于 H 0 H_0 H0计算出的期望频数,A与E之差称为残差;
    • 残差可以表示某一个类别观察值和理论值的偏离程度,由于残差有正有负,相加后会彼此抵消,为此可以将残差平方后求和;
    • 残差大小是一个相对概念,相对于期望频数为10时,期望频数为20的残差非常大,但相对于期望频数为1000时20的残差就很小了,为此,将残差平方除以期望频数再求和,以估计观察频数与期望频数的差别。
    • χ 2 = ∑ ( A − E ) 2 E = ∑ i = 1 k ( A i − E i ) 2 E i ( i = 1 , 2 , 3 , … , k ) \chi^{2}=\sum \frac{(A-E)^{2}}{E}=\sum_{i=1}^{k} \frac{\left(A_{i}-E_{i}\right)^{2}}{E_{i}} \quad(i=1,2,3, \ldots, k) χ2=E(AE)2=i=1kEi(AiEi)2(i=1,2,3,,k)
  • 检验的应用
    • 拟合优度检验(chi-squared test goodness of fit)
      • 实际执行多次试验得到的观察次数,与期望次数相比较,称为卡方适度检验,即在于检验二者接近的程度,利用样本数据以检验总体分布是否为某一特定分布的统计方法;
      • 零假设:观察分布等于期望分布;
      • χ 2 = ∑ i = 1 k ( A i − n p i ) 2 n p i ( i = 1 , 2 , 3 , … , k ) \chi^{2}=\sum_{i=1}^{k} \frac{\left(A_{i}-n p_{i}\right)^{2}}{n p_{i}} \quad(i=1,2,3, \ldots, k) χ2=i=1knpi(Ainpi)2(i=1,2,3,,k)
      • 其中, n n n为总频数, p i p_i pi为i水平的期望频率,i水平的期望频数 E i E_i Ei等于总频数 n n n×i水平的期望概率 p i p_i pi;
      • 确定自由度;选择显著性水平;
      • 比较临界值和统计量( χ 2 \chi^{2} χ2值),若临界值大于统计量,差异不显著,接受零假设;否则拒绝。
    • 独立性检验(chi-squared test of independence)
      • 卡方独立性检验是用来检验两个属性间是否独立,以一个变量为行,另一个变量为列,组成相依表;
      • 零假设:两者相互独立,这样相依表的分布应该满足乘法公式,即两个独立事件一起发生的概率等于分别发生的概率之积;
      • χ 2 = ∑ i = 1 c ∑ j = 1 r ( o i j − e i j ) 2 e i j \chi^{2}=\sum_{i=1}^{c} \sum_{j=1}^{r} \frac{\left(o_{i j}-e_{i j}\right)^{2}}{e_{i j}} χ2=i=1cj=1reij(oijeij)2,其中 o i j o_{i j} oij是联合事件 ( A i , B j ) (A_i,B_j) (Ai,Bj)的观测频度(即实际计数), e i j e_{i j} eij ( A i , B j ) (A_i,B_j) (Ai,Bj)的期望频度, e i j = count ⁡ ( A = a i ) × count ⁡ ( B = b j ) n e_{i j}=\frac{\operatorname{count}\left(A=a_{i}\right) \times \operatorname{count}\left(B=b_{j}\right)}{n} eij=ncount(A=ai)×count(B=bj),其中n是总计数, count ⁡ ( A = a i ) \operatorname{count}\left(A=a_{i}\right) count(A=ai)是A中具有值 a i a_i ai的个数, count ⁡ ( B = b j ) \operatorname{count}\left(B=b_{j}\right) count(B=bj)是B中具有值 b j b_j bj的个数;
      • 根据 χ 2 \chi ^2 χ2分布的百分点表,查找自由度 ( r − 1 ) × ( c − 1 ) (r-1)\times(c-1) (r1)×(c1)下的显著水平,计算 χ 2 \chi^{2} χ2值大于该值,拒绝假设,两属性相关,反之独立。
    • 卡方检验的样本量要求:一般认为对于卡方检验中的每一个单元格,要求其最小期望频数均大于1,且至少有4/5的单元格期望频数大于5,此时使用卡方分布计算出的概率值才是准确的。如果数据不符合要求,可以采用确切概率法进行概率的计算。

Python实现

卡方分布、卡方独立性检验和拟合性检验理论及其python实现

ChiMerge算法

算法原理

  • ChiMerge 是监督的、自底向上的(即基于合并的)数据离散化方法。它依赖于卡方 χ 2 \chi^{2} χ2检验:具有最小卡方值的相邻区间合并在一起,直到满足确定的停止准则。
  • 高质量的离散化应该是:区间内一致,区间之间区分明显。
  • ChiMerge算法流程
    • 初始化:根据要离散的属性对实例进行排序:将数值属性的每个值看作一个区间(左闭右开);
    • 自底向上区间合并,当满足停止条件的时候(高于预定卡方阈值),停止合并。
      • 计算每一对相邻区间的卡方值;
      • 将卡方值最小的一对区间合并。
  • 卡方阈值的选择:先选择显著性水平,再由公式得到对应的卡方值。得到卡方值需要指定自由度,自由度比类别数量小1。例如,有3类,自由度为2,则90%置信度(10%显著性水平)下,卡方的值为4.6。阈值的意义在于,类别和属性独立时,有90%的可能性,计算得到的卡方值会小于4.6,这样,大于阈值的卡方值就说明属性和类不是相互独立的,不能合并。如果阈值选的大,区间合并就会进行很多次,离散后的区间数量少、区间大。
  • ChiMerge算法推荐使用0.90、0.95、0.99置信度,最大区间数取10到15之间。
  • 下图以部分iris数据集的sepal-length属性为例,计算不同区间的 χ 2 \chi_{2} χ2值,将其与预定义阈值比较,合并低于预定义阈值的区间。

Python实现

from collections import Counter
from time import ctime
 
def read(file):
    list_data=[]
    with open(file, 'r', encoding='utf-8') as fp:
        for line in fp:
            line=line.strip()
            if line!='':
                list_data.append(line.split(','))
    return list_data

def stas_count(list_data,i):
    ''' 统计将每个属性具体对应的类别,
     返回形如[['4.3', 'Iris-setosa', 1], ['4.4', 'Iris-setosa', 3],...]的列表'''
    list_vc=[] # list_value+class
    for r in list_data:
        list_vc.append(str(r[i]+','+r[4]))

    list_vcc=[] # list_value-class-count
    for k,v in dict(Counter(list_vc)).items():
        list_tmp = k.split(',')
        list_tmp.append(v)
        list_vcc.append(list_tmp)
 
    return list_vcc
 
def collect(list_data,i):
    '''根据第i个属性特征构造一个数据结构,以便使用ChiMerge算法。
    这个数据结构是形如 [('4.3', [1, 0, 0]), ('4.4', [3, 0, 0]),...]的列表,
    每一个元素是一个元组,
    元组的第一项是字符串,表示区间左端点,元组的第二项是一个列表,表示在此区间各个类别的实例数目'''
    list_cvv=stas_count(list_data,i)
    log_dic={}
    for record in list_cvv:
        if record[0] not in log_dic.keys():
            log_dic[record[0]]=[0,0,0]
        if record[1]=='Iris-setosa':
            log_dic[record[0]][0]=record[2]
        elif record[1]=='Iris-versicolor':
            log_dic[record[0]][1]=record[2]
        elif record[1]=='Iris-virginica':
            log_dic[record[0]][2]=record[2]
        else:
            raise TypeError("Data Exception")
    list_tuple=sorted(log_dic.items())
    
    return list_tuple
 
 
def combine(a,b):
    '''  a=('4.4', [3, 1, 0]), b=('4.5', [1, 0, 2])
         combine(a,b)=('4.4', [4, 1, 2])  '''
    c=a[:] # c[0]=a[0]
    for i in range(len(a[1])):
        c[1][i]+=b[1][i]
    return c

def chi2(A):
    m=len(A)
    k=len(A[0])
    R=[]
    for i in range(m):
        sum=0
        for j in range(k):
            sum+=A[i][j]
        R.append(sum)
    C=[]
    for j in range(k):
        sum=0
        for i in range(m):
            sum+=A[i][j]
        C.append(sum)
    N=0
    for ele in C:
        N+=ele
    M=0
    for ele in R:
        M+=ele
    assert  M==N
    res=0
    for i in range(m):
        for j in range(k):
            Eij=R[i]*C[j]/N
            if Eij!=0:
                res=res+(A[i][j]-Eij)**2/Eij
    return res

def ChiMerge(list_tuple,max_interval):
    num_interval=len(list_tuple)
    while num_interval>max_interval:               
        num_pair=num_interval-1 # 需两两配对,故减1
        chi_values=[]
        for i in range(num_pair):
            arr=[list_tuple[i][1],list_tuple[i+1][1]]
            chi_values.append(chi2(arr))
        min_chi=min(chi_values) # 最小卡方值
        for i in range(num_pair-1,-1,-1): # 合并最小值相邻区间
            if chi_values[i]==min_chi:
                list_tuple[i]=combine(list_tuple[i],list_tuple[i+1])
                list_tuple[i+1]='Merged'
        while 'Merged' in list_tuple:
            list_tuple.remove('Merged')
        num_interval=len(list_tuple)
    split_points=[record[0] for record in list_tuple]
    
    return split_points


def run(path):
    list_iris =read(path)
    max_interval=6 # 离散化区间个数
    num_attr=4 # 属性类别
    for i in range(num_attr):
        list_tuple=collect(list_iris,i)
        split_points=ChiMerge(list_tuple,max_interval) # discretize data using ChiMerge algorithm 
        print(split_points)
 

if __name__=='__main__':
    print('Start: ' + ctime())
    run('iris.data')
    print('End: ' + ctime())

参考

  1. 卡方检验详解 https://www.jianshu.com/p/fcfac399de13
  2. 卡方检验 https://blog.csdn.net/qunxingvip/article/details/50447864
  3. 卡方分布、卡方独立性检验和拟合性检验理论及其python实现 https://www.cnblogs.com/Yuanjing-Liu/p/9252844.html
  4. ChiMerge算法 https://markdown.blog.csdn.net/article/details/50449376?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control
  5. ChiMerge: Discretization of Numeric Attribute https://www.aaai.org/Papers/AAAI/1992/AAAI92-019.pdf
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值