4、特征选择(filter):卡方检验特征筛选

卡方检验特征筛选

  • 一、卡方检验(Chi-Squared Test)基本原理
  • 二、离散变量之间的卡方检验
    • 2.1、提出假设
    • 2.2、采集数据
    • 2.3、计算统计量
    • 2.4、事件发生概率计算与统计推断
  • 三、连续变量与离散变量的卡方检验
  • 四、python实现卡方检验
    • 4.1、自实现卡方检验
    • 4.2、借助scipy进行卡方检验
    • 4.3、借助sklearn进行卡方检验

一、卡方检验(Chi-Squared Test)基本原理

  通常情况下,卡方检验是针对于离散变量的独立性检验,卡方检验的零假设为两个离散变量相互独立。在特征选择中其用于标签和特征的判别,就能借此判断某特征和标签是不是独立的,如果是,则说明特征对标签的预测毫无帮助。因此在很多时候,卡方检验都是非常重要的剔除无关特征的方法。

卡方检验的基本原理
  卡方检验是以 x 2 x^2 x2分布为基础的一种常用假设检验方法,它的原假设H0是:观察频数与期望频数没有差别。
  该检验的基本思想是:首先假设H0成立,基于此前提计算出 x 2 x^2 x2值,它表示观察值与理论值之间的偏离程度。再根据 x 2 x^2 x2分布及自由度可以确定在H0假设成立的情况下获得当前统计量及更极端情况的概率P。如果P值很小,说明观察值与理论值偏离程度太大,应当拒绝原假设,表示变量之间有显著差异;否则接受原假设,尚不能认为样本所代表的实际情况和理论假设有差别。至于 x 2 x^2 x2在每个具体研究中究竟要大到什么程度才能拒绝H0,则要借助于卡方分布求出所对应的P值来确定。
卡方值的计算与意义
   x 2 x^2 x2值表示观察值与理论值之间的偏离程度。计算这种偏离程度的基本思路如下。
  设A代表某个类别的观察频数,E代表基于H0计算出的期望频数,A与E之差称为残差。
  -显然,残差可以表示某一个类别观察值和理论值的偏离程度,但如果将残差简单相加以表示各类别观察频数与期望频数的差别,则有一定的不足之处。因为残差有正有负,相加后会彼此抵消,总和仍然为0,为此可以将残差平方后求和。
  另一方面,残差大小是一个相对的概念,相对于期望频数为10时,期望频数为20的残差非常大,但相对于期望频数为1 000时20的残差就很小了。考虑到这一点,人们又将残差平方除以期望频数再求和,以估计观察频数与期望频数的差别。
其计算公式为
χ 2 = ∑ ( A − E ) 2 E = ∑ i = 1 k ( A i − E i ) 2 E i = ∑ i = 1 k ( A i − n p i ) 2 n p i    ( i = 1 , 2 , 3 , … , k ) \chi^2=\sum \frac{(A-E)^2}{E}=\sum_{i=1}^k \frac{(A_i-E_i)^2}{E_i}=\sum_{i=1}^k \frac{(A_i-np_i)^2}{np_i}  (i=1,2,3,…,k) χ2=E(AE)2=i=1kEi(AiEi)2=i=1knpi(Ainpi)2  (i=123k)
  其中,Ai为i水平的观察频数,Ei为i水平的期望频数,n为总频数,pi为i水平的期望频率。i水平的期望频数Ei等于总频数n×i水平的期望概率pi,k为单元格数。当n比较大时,χ2统计量近似服从k-1(计算Ei时用到的参数个数)个自由度的卡方分布。
它最初是由英国统计学家Karl Pearson在1900年首次提出的,因此也称之为Pearson x 2 x^2 x2

二、离散变量之间的卡方检验

2.1、提出假设

在此,通过Telco数据集来阐述卡方检验的过程,挑选原数据集的Contract字段和标签来进行卡方检验,即判断这两个离散变量是否相互独立。有如下假设:

H 0 : C o n t r a c t 字段和标签相互独立 H 1 : C o n t r a c t 字段和标签不相互独立 H_0:Contract字段和标签相互独立\\ H_1:Contract字段和标签不相互独立 H0:Contract字段和标签相互独立H1:Contract字段和标签不相互独立

2.2、采集数据

  挑选原数据集的Contract字段和标签来进行卡方检验,即判断这两个离散变量是否相互独立。对于Contract字段来说,按月付费用户为0、年度付费用户标记为1、两年一次付费用户标记为2。标签是Churn代表是否流失,0表示未流失、1表示流失:

  对于卡方检验来说,需要对原始数据集进行关联汇总,并形成列联表,其实也就是按照标签不同取值进行分组求和,结果如下:

观测值
Churn Contract
0:按月付费用户 1:年度付费用户 2:两年一次付费用户标记 Churn-all
0:未流失 1695 973 1233 3901
1:流失 1226 125 30 1381
Contract_all 2921 1098 1263 5282

2.3、计算统计量

  接下来,我们进一步进行统计量的设计。设计统计量的最终目的是为了能够量化的判断当前数据所表现出的情况是否能够支持或者拒绝原假设。当前检验的零假设是两个离散特征相互独立,而所谓的两个变量相互独立,指的是任意一个变量的取值不受到另一个变量取值的影响,对应当前数据,则是指Churn取得0或者1,不受Contract取值影响(也就是用户是否流失和签订合约形式无关)。这里我们可以试想,如果假设成立,即两个变量真的相互独立,那么在总体数据量不变的情况下,两个变量的列联表是可以有一个期望观测值的,通过对比理论上的期望观测值和真实值,我们就能够判断假设是否成立。这就好比在抛硬币的例子中,抛了10次硬币,如果“硬币质地均匀”的假设成立,则最有可能发生的情况就是5次正面5次反面,而由于实验数据距离期望假设较远,我们最终在二项分布统计量提供的概率结果协助下,拒绝了原假设。

假各变量总体数据分布不变,取值分布如下:
P ( C o n t r a c t = 0 ) = 2921 5282 ≈ 0.553 P(Contract=0) = \frac{2921}{5282} \approx0.553 P(Contract=0)=528229210.553
P ( C o n t r a c t = 1 ) = 1098 5282 ≈ 0.2078 P(Contract=1) = \frac{1098}{5282} \approx0.2078 P(Contract=1)=528210980.2078
P ( C o n t r a c t = 1 ) = 1263 5282 ≈ 0.2391 P(Contract=1) = \frac{1263}{5282} \approx 0.2391 P(Contract=1)=528212630.2391
同时,ℎ的取值分布如下:
P ( C h u r n = 0 ) = 3901 5282 ≈ 0.7385 P(Churn=0) = \frac{3901}{5282} \approx 0.7385 P(Churn=0)=528239010.7385
P ( C h u r n = 1 ) = 1381 5282 ≈ 0.2614 P(Churn=1) = \frac{1381}{5282} \approx 0.2614 P(Churn=1)=528213810.2614

现依据零假设,和ℎ相互独立,因此对于任意一名用户,同时=0且ℎ=0的概率为:

P ( C o n t r a c t = 0 , C h u r n = 0 ) = P ( C o n t r a c t = 0 ) ∗ P ( C h u r n = 0 ) = 0.533 ∗ 0.7385 = 0.39 \begin{aligned} &P(Contract=0, Churn=0) \\ &= P(Contract=0) * P(Churn=0) \\ &= 0.533 * 0.7385 = 0.39 \end{aligned} P(Contract=0,Churn=0)=P(Contract=0)P(Churn=0)=0.5330.7385=0.39

而目前,总共有5282名用户,因此在零假设的情况下,=0且ℎ=0的用户总数期望为: E 0 , 0 = P ( C o n t r a c t = 0 , C h u r n = 0 ) ∗ 5282 = 0.39 ∗ 5282 = E_{0, 0} = P(Contract=0, Churn=0) * 5282 = 0.39*5282= E0,0=P(Contract=0,Churn=0)5282=0.395282=2157,而真实的统计结果是=0且ℎ=0总用户有1695,和期望人数有些差异,很明显,当实际人数和期望人数的差异越大,我们就越有理由怀疑零假设。但这种差异是不能通过和ℎ的一组取值结果来判定,我们还需要进一步查看列联表中其他位置的期望频数。

对于每个单元格,期望频数的计算应该是 ( C h u r n _ a l l [ i ] t o l ) ∗ ( C o n t r a c t _ a l l [ j ] t o l ) ∗ t o l (\frac{Churn\_all[i]}{tol}) * (\frac{Contract\_all[j]}{tol}) * tol (tolChurn_all[i])(tolContract_all[j])tol,等于 C h u r n _ a l l [ i ] ∗ C o n t r a c t _ a l l [ j ] t o l \frac{Churn\_all[i] * Contract\_all[j]}{tol} tolChurn_all[i]Contract_all[j]

期望频数
0:按月付费用户 1:年度付费用户 2:两年一次付费用户标记
0:未流失 2157.29 810.92 932.78
1:流失 763.707 287.07 330.22

为了衡量二者的差异,我们可以构造如下统计量:

X 2 = ∑ i = 1 m ∑ j = 1 n ( O i , j − E i , j ) 2 E i , j \mathcal{X}^2 = \sum_{i=1}^{m}\sum_{j=1}^{n}\frac{(O_{i,j}-E_{i,j})^2}{E_{i,j}} X2=i=1mj=1nEi,j(Oi,jEi,j)2

其中i、j代表列联表的行和列, O i , j O_{i,j} Oi,j表示i行j列的观测值(observe)、 E i , j E_{i,j} Ei,j表示期望值。而此处的 X 2 \mathcal{X}^2 X2就是卡方值,也就是卡方检验中的统计量。

根据以上观测值与期望值,求得 x 2 x^2 x2
x 2 = ( 1695 − 2157 ) 2 2157 + ( 973 − 810 ) 2 8110 + ( 1233 − 932 ) 2 932 + ( 1226 − 763 ) 2 763 + ( 125 − 287 ) 2 287 + ( 30 − 330 ) 2 330 = 872 x^2 = \frac{(1695-2157)^2}{2157}+\frac{(973-810)^2}{8110}+\frac{(1233-932)^2}{932}+\frac{(1226-763)^2}{763}+\frac{(125-287)^2}{287}+\frac{(30-330)^2}{330}=872 x2=2157(16952157)2+8110(973810)2+932(1233932)2+763(1226763)2+287(125287)2+330(30330)2=872

对于二维列联表来说,自由度就是 ( m − 1 ) ∗ ( n − 1 ) (m-1)*(n-1) (m1)(n1),行数-1和列数-1的乘积,即在本例子中自由度为2.

2.4、事件发生概率计算与统计推断

  通过查阅卡方分布表中, X 2 ( 2 ) = 872 \mathcal{X}^2(2)=872 X2(2)=872发生的概率不足0.001,也就是说Contract和Churn相互独立的概率不足0.001,有充分的理由拒绝原假设。
4、特征选择(filter):卡方检验特征筛选_第1张图片

三、连续变量与离散变量的卡方检验

  通常来说卡方检验是作用于离散变量之间的独立性检验,但sklearn中的卡方检验只需要参与检验的其中标签是离散特征即可,即sklearn中的卡方检验不仅可以作用于两个离散变量、还可以作用于连续变量和离散变量之间。

  • 连续变量的卡方检验过程

  其实关于连续变量和离散变量的卡方检验,其根本过程与离散变量间的卡方检验并没有本质区别,都是通过比较期望观测值和实际值来判断两个变量是否独立,只不过对于连续变量来说,无法通过列联表的方式进行频数的汇总统计。此处以MonthlyCharges作为连续变量与标签(label)进行卡方检验,并说明该计算过程:

  • 先计算出标签不同取值的占比,比如:0类占0.7,1类占比0.3

  • 计算连续特征总行,比如为100,其中0类有55,1类有45

  • 在原假设为相互独立的情况下,0类的期望值为1000.7=70,1类的期望值为1000.3=30

  • 计算统计量: x 2 = ( 55 − 70 ) 2 70 + ( 45 − 30 ) 2 30 = 1.7 x^2 = \frac{(55-70)^2}{70}+\frac{(45-30)^2}{30} = 1.7 x2=70(5570)2+30(4530)2=1.7

  • 自由度为离散变量不同取值-1,在该例子中自由为1,查阅卡方检验表得 x 2 ( 1 ) = 101.7 的概率不足 0.01 x^2(1)=101.7的概率不足0.01 x2(1)=101.7的概率不足0.01,有理由拒绝原假设,则MonthlyCharges与label并不是相互独立的。

  • 连续变量卡方检验注意事项

  注意的是,连续变量的取值毕竟不是频数结果,最终的卡方值会严重受到连续变量的量纲影响,而这种影响对统计推断而言是无意义的;因此,在实际进行连续变量的卡方检验过程中,建议先对原始变量进行标准化处理,该过程会将所有连续变量取值放缩至类似水平,同样也会将p值和卡方值放缩至同样水平,然后我们在单独针对连续变量进行BestK筛选,而不建议同时比较连续变量和离散变量的K值然后在一个流程中进行筛选(因为连续变量的p值和卡方值没有绝对大小的意义)。

四、python实现卡方检验

4.1、自实现卡方检验

4.2、借助scipy进行卡方检验

4.3、借助sklearn进行卡方检验

import numpy as np
import pandas as pd
import itertools


# 构建数据源

Contract = []
label = []
count = [1695,973,1233,1226,125,30]
c = 0
for i, j in itertools.product(range(2), range(3)): 
    label.extend([str(i)]*count[c])
    Contract.extend([str(j)]*count[c])
    c += 1
    
df =pd.DataFrame({ 'Contract':Contract, 'label':label})

# 自实现卡方检验

# 1计算Contract和Churn取值的期望分布

df_count = pd.crosstab(df['label'], df['Contract'])

df_count_all = df_count.copy()

df_count_all.loc['Contract-all'] = df_count.sum(0)
df_count_all['Churn-all'] = df_count_all.sum(1)

# 2每个变量的统计结果计算期望频数

Contract_all = df_count_all.loc['Contract-all', :].copy()
Churn_all = df_count_all.loc[:, 'Churn-all'].copy()

# 3对于每个单元格,期望频数的计算
df_count_temp = df_count.copy()
for i, j in itertools.product(range(2), range(3)):
    Eij = Churn_all[i] * Contract_all[j] / df.shape[0]
    df_count_temp.iloc[i, j] = Eij
# 计算统计量
chi_value = np.sum(np.power(df_count_temp - df_count, 2) / df_count_temp).sum()
chi_value

# 借助scipy进行卡方检验

from scipy import stats
stats.chi2_contingency(observed = df_count)

# 借助sklearn进行卡方检验特征筛选
from sklearn.feature_selection import chi2
chi2(df['Contract'].values.reshape(-1, 1), df['label'].values.reshape(-1, 1))

你可能感兴趣的:(特征工程,机器学习)