写点什么

数据预处理和特征工程 - 特征选择 - 相关性过滤 - 卡方过滤

  • 2022-11-13
    山东
  • 本文字数:3405 字

    阅读完需:约 11 分钟

方差挑选完毕之后,我们就要考虑下一个问题:相关性了。我们希望选出与标签相关且有意义的特征,因为这样的特征能够为我们提供大量信息。


分布可以用来检验模型的适合性,变量的独立性等,对象是类别变量。的检验公式是

其中,是 observation,观测数据,是 Expectation,期望数据

卡方分布的思想:我们先假设数据服从某一分布或者是某一模型,然后通过假设,计算出数据应该有的样子,再用现实中观察到的值比较,即代入卡方检验公式。如果观测值与期望值相差值很大,就很大,我们就会拒绝假设对于列联表,假设数据服从的模型就是每一行列最后的统计量,每一格,然后计算其与……

例:

假设这里有三个搜索引擎,我们假设:三个算法一样好(不同算法对搜索结果的好坏无影响、属性和组别无关),:三个算法不一样好一般思路我们是假设成立,对于取定的显著性水平,若计算出的H{0}H

{0}H_{1}对于本例,对于第一行第一列,有

也就是表中括号内的数字。由此,我们可以得到

得到后我们还需要知道对应分布的自由度

因为我们知道了 Total 行和 Total 列,因此,对于某一行假设有个元素,只要我们确定个元素,就能固定剩余一个元素的取值。对于列同理。因此自由度为

对于上例,有

自由度为 2 的卡方分布有 $\chi^{2}{0.050}=5.99147,\chi^{2}{0.010}=9.21034\alpha=0.055.99147<6.12H_{0}\alpha=0.01H_{0}H_{1}$

我们这里:属性和组别无关,不好理解,我们可以想:属性和组别相关,当属性与组别完全相关,显然,也就是越小,接受的可能性越大;对于来说,越小,对应的可能性越小,因此我们是要更大的,才能接受

视频作者:林泰峰老师链接:十五分钟理解卡方分布和卡方检验_哔哩哔哩_bilibili


卡方过滤是专门针对离散型标签(即分类问题)的相关性过滤。卡方检验类 feature_selection.chi2 计算每个非负特征和标签之间的卡方统计量,并依照卡方统计量由高到低为特征排名(卡方越大特征越好)。再结合 feature_selection.SelectKBest 这个可以输入”评分标准“来选出前 K 个分数最高的特征的类,我们可以借此除去最可能独立于标签,与我们分类目的无关的特征。


为什么卡方越大越好,这是因为卡方越大,根据上面的数学推理,我们可以认为标签和特征无关,就是二者之间独立的可能性越大。对于独立的标签和特征,如果我们知道了特征的取值,但由于二者独立,即其中一个的取值不影响另一个,因此该特征对于标签是哪个的贡献并不大,所以我们要求卡方越大越好


如果卡方检验检测到某个特征中所有的值都相同,会提示我们使用方差先进行方差过滤。


SelectKBest(score_func=<function f_classif at 0x00000202ABD80620>, k=10)# score:评分标准# k:保留k个最优特征
复制代码


from sklearn.ensemble import RandomForestClassifier as RFCfrom sklearn.model_selection import cross_val_scorefrom sklearn.feature_selection import SelectKBestfrom sklearn.feature_selection import chi2
# 假设在这里我知道我需要300个特征X_fschi = SelectKBest(chi2,k=300).fit_transform(X_fsvar,y)X_fschi.shape---(42000, 300)
cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean()---0.9333098667649198
复制代码


分数降低了,说明我们这里卡方过滤的效果并不好,不如没过滤,我们需要更换 k 值或者换方法

选取超参数 k

我们可以话学习曲线,但由于过于耗时间,所以实际应用不考虑


import matplotlib.pyplot as pltscore = []for i in range(350,200,-10):    X_fschi = SelectKBest(chi2,k=i).fit_transform(X_fsvar,y)    once = cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean()    score.append(once)
plt.plot(range(350,200,-10),score)plt.show()
复制代码



通过这条曲线,我们可以观察到,随着 k 值的不断增加,模型的表现不断上升,这说明,k 越大越好,数据中所有的特征都是与标签相关的。


实际上,我们是通过指定 p 来选择 k,一般指定 p=0.05 或 0.01,要求特征对于标签的 p 值≤0.05 或 0.01



所谓差异不是自然形成的,可以这样理解,假设标签可能取值为 0,1,特征可能取值为 2,3,当特征取 2 的时候,标签取 0 的可能性大于取 1 的时候的可能性


从特征工程的角度,我们希望选择卡饭值很大,p 值小于 0.05 的特征,即和标签是相关的特征。实际上我们调用 SelectKBest 之前,我们可以直接从 chi2 实例化后的模型中获得各个特征所对应的卡方值和 P 值,由此来过滤 p 值>0.05 的特征


chi2(X, y)# 返回两个值,分别是卡方,p值,
复制代码


chivalue, pvalues_chi = chi2(X_fsvar,y)chivalue.shape,pvalues_chi.shape# 392个特征---((392,), (392,))
k = chivalue.shape[0] - (pvalues_chi > 0.05).sum()# True=1,False=0k # p值≤0.05特征的数量---392
X_fschi = SelectKBest(chi2,k).fit_transform(X_fsvar,y)# 这里k=392也就是没过滤效果cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean
复制代码


可以观察到,所有特征的 p 值都是≤0.05,这说明对于 digit recognizor 这个数据集来说,方差验证已经把所有和标签无关的特征都剔除了,或者这个数据集本身就不含与标签无关的特征。在这种情况下,舍弃任何一个特征,都会舍弃对模型有用的信息,而使模型表现下降,因此在这种情况下,在我们对计算速度感到满意时,我们不需要使用相关性过滤来过滤我们的数据。如果我们认为运算速度太缓慢,那我们可以酌情删除一些特征,但前提是,我们必须牺牲模型的表现。


卡方验证的 python 实现(其实我觉得还挺有用的)

from sklearn.preprocessing import LabelBinarizer
from scipy.special import chdtrc
import numpy as np
import pandas as pd

X = np.array([3.4, 3.4, 3. , 2.8, 2.7, 2.9, 3.3, 3. , 3.8, 2.5])
y = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2, 2])

y = LabelBinarizer().fit_transform(y)

observed = y.T.dot(X)
observed # 不同y的观测值
---
array([ 9.8,  8.4, 12.6])

feature_count = X.sum().reshape(-1,1)
feature_count # X求和,用于算预测值
---
array([[30.8]])

class_prob = y.mean(axis=0).reshape(1,-1)
class_prob # 不同y出现的次数来估计概率
---
array([[0.3, 0.3, 0.4]])

expected = np.dot(class_prob.T, feature_count)
expected # 不同y的期望值
---
array([[ 9.24],
    [ 9.24],
    [12.32]])

chi2 = ((observed.reshape(-1,1) - expected) ** 2 / expected).sum(axis=0) # 卡方公式
chi2
---
array([0.11666667])

p = chdtrc(3-1,chi2) # 用自由度和卡方值来算p值
p
---
array([0.94333545])

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
X = np.array([[3.4, 3.4, 3. , 2.8, 2.7, 2.9, 3.3, 3. , 3.8, 2.5],[0, 0, 9, 0, 0, 0, 0, 0, 0, 0]])
# 添加[0, 0, 9, 0, 0, 0, 0, 0, 0, 0],为了更好的理解什么叫标签与特征相关,也就是说,如果我们给定x=0,那么我们就能有很大概率y=0
y = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2, 2])

chivalue, pvalues_chi = chi2(X.T,y)
chivalue, pvalues_chi
---
(array([ 0.11666667, 21. ]), array([9.43335450e-01, 2.75364493e-05]))

X = SelectKBest(chi2,k=1).fit_transform(X.T,y)
X
---
array([[0.],
    [0.],
    [9.],
    [0.],
    [0.],
    [0.],
    [0.],
    [0.],
    [0.],
    [0.]])

作者:hellpanderr 链接:用户对问题“SelectKBest (chi2)如何计算分数?”的回答 - 问答 - 腾讯云开发者社区-腾讯云 (tencent.com)


视频作者:菜菜TsaiTsai链接:【技术干货】菜菜的机器学习sklearn【全85集】Python进阶_哔哩哔哩_bilibili


发布于: 刚刚阅读数: 3
用户头像

一个烟台人 2022-09-14 加入

还未添加个人简介

评论

发布
暂无评论
数据预处理和特征工程-特征选择-相关性过滤-卡方过滤_Python_烧灯续昼2002_InfoQ写作社区