3(1).特征选择---过滤法(特征相关性分析)
一、绘图判断
一般对于强相关性的两个变量,画图就能定性判断是否相关
1 2 3 4 5 6 7 8 9 | # 散点图矩阵初判多变量间关系 data = pd.DataFrame(np.random.randn( 200 , 4 ) * 100 , columns = [ 'A' , 'B' , 'C' , 'D' ]) pd.plotting.scatter_matrix(data,figsize = ( 8 , 8 ), c = 'k' , marker = '+' , diagonal = 'hist' , alpha = 0.8 , range_padding = 0.1 ) data.head() |
- 折线图
二、单特征
1.方差选择法
删除方差为0的特征

# 计算变量的方差 # 如果方差接近于0,也就是该特征的特征值之间基本上没有差异,这个特征对于样本的区分并没有什么用,剔除 from sklearn.feature_selection import VarianceThreshold selector = VarianceThreshold(threshold=0.1)#默认threshold=0.0 selector.fit_transform(offline_data_shuffle1[numerical_features]) # 查看各个特征的方差, selector.variances_ ,len(selector.variances_) # 特征对应方差 all_used_features_dict = dict(zip(numerical_features,selector.variances_ )) all_used_features_dict
三、数值特征与数值特征
1.协方差
- 如果协方差为正,说明X,Y同向变化,协方差越大说明同向程度越高;
- 如果协方差维负,说明X,Y反向运动,协方差越小说明反向程度越高;
- 如果两个变量相互独立,那么协方差就是0,说明两个变量不相关。
2.pearson系数
- 相关系数也可以看成协方差:一种剔除了两个变量量纲影响、标准化后的特殊协方差。
- 可以反映两个变量变化时是同向还是反向,如果同向变化就为正,反向变化就为负。由于它是标准化后的协方差,因此更重要的特性来了,它消除了两个变量变化幅度的影响,而只是单纯反应两个变量每单位变化时的相似程度。
- 相关系数分类:
- 0.8-1.0 极强相关;0.6-0.8 强相关;0.4-0.6 中等程度相关;0.2-0.4 弱相关;0.0-0.2 极弱相关或无相关
- 假设: 对于Pearson r相关性,两个变量都应该是正态分布的(正态分布变量具有钟形曲线)。其他假设包括线性和同态性。线性度假设分析中每个变量之间存在直线关系,同质性假定数据在回归线上正态分布。
皮尔逊系数/斯皮尔曼系数:衡量2个变量之间的线性相关性。 .00-.19 “very weak” .20-.39 “weak” .40-.59 “moderate” .60-.79 “strong” .80-1.0 “very strong”
- 如果>0.8,说明2个变量有明显线性关系,只保留一个,保留与label的皮尔逊系数较大的那个变量或者保留lightgbm AUC最大的那个;
优点:可以通过数字对变量的关系进行度量,并且带有方向性,1表示正相关,-1表示负相关,可以对变量关系的强弱进行度量,越靠近0相关性越弱。
缺点:无法利用这种关系对数据进行预测,简单的说就是没有对变量间的关系进行提炼和固化,形成模型。要利用变量间的关系进行预测,需要使用到下一种相关分析方法,回归分析。
使用场景:当两个变量的标准差都不为零时,相关系数才有定义,皮尔逊相关系数适用于:
- 两个变量之间是线性关系,都是连续数据。
- 两个变量的总体是正态分布,或接近正态的单峰分布。
- 两个变量的观测值是成对的,每对观测值之间相互独立。
举例1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 方法1,numpy.corrcoef,求多个数组的相关系数 import numpy as np np.corrcoef([a,b,c,d]) # 方法2.计算特征间的pearson相关系数,画heatmap图 plt.figure(figsize = ( 25 , 25 )) corr_values1 = data[all_used_features].corr() # pandas直接调用corr就能计算特征之间的相关系数 sns.heatmap(corr_values1, annot = True ,vmax = 1 , square = True , cmap = "Blues" ,fmt = '.2f' ) plt.tight_layout() # plt.savefig('prepare_data/columns37.png',dpi=600) plt.show() # 方法3.Scipy的pearsonr方法能够同时计算相关系数和p-value import numpy as np from scipy.stats import pearsonr np.random.seed( 0 ) size = 300 x = np.random.normal( 0 , 1 , size) print ( "Lower noise" , pearsonr(x, x + np.random.normal( 0 , 1 , size))) print ( "Higher noise" , pearsonr(x, x + np.random.normal( 0 , 10 , size))) |
举例2:计算各特征与label的相关系数,并画出直方图
x_cols = [col for col in train_csv.columns if col not in [ '信用分' ] if train_csv[col].dtype! = 'object' ] #处理目标的其他所有特征 labels = [] values = [] for col in x_cols: labels.append(col) values.append(np.corrcoef(train_csv[col].values, train_csv.信用分,values)[ 0 , 1 ]) corr_df = pd.DataFrame({ 'col_labels' :labels, 'corr_values' :values}) corr_df = corr_df.sort_values(by = 'corr_values' ) ind = np.arange( len (labels)) width = 0.5 fig,ax = plt.subplots(figsize = ( 12 , 40 )) rects = ax.barh(ind, np.array(corr_df.corr_values.values), color = 'y' ) ax.set_yticks(ind) ax.set_yticklabels(corr_df.col_labels.values, rotation = 'horizontal' ) ax.set_xlabel( 'Correlation coefficient' ) ax.set_title( 'Correlation coefficient of the variables' ) |
3.距离相关系数
距离相关系数是为了克服Pearson相关系数的弱点而生的。在 和
这个例子中,即便Pearson相关系数是
,我们也不能断定这两个变量是独立的(有可能是非线性相关);但如果距离相关系数是
,那么我们就可以说这两个变量是独立的。
尽管有MIC和距离相关系数在了,但当变量之间的关系接近线性相关的时候,Pearson相关系数仍然是不可替代的。第一、Pearson相关系数计算速度快,这在处理大规模数据的时候很重要。第二、Pearson相关系数的取值区间是[-1,1],而MIC和距离相关系数都是[0,1]。这个特点使得Pearson相关系数能够表征更丰富的关系,符号表示关系的正负,绝对值能够表示强度。当然,Pearson相关性有效的前提是两个变量的变化关系是单调的。
4.一元回归及多元回归
准备工作:
- 第一确定变量的数量
- 第二确定自变量和因变量
一元回归:y = b0 + b1x
多元回归:y = b0 + b1x1 + b2x2 + ... + bnxn
5.去掉不相关的列
# 去掉日期列 def drop_date(data): columns = list (data.columns) not_date_columns = [] for column in columns: tmp_num = data[column]. max () if str (tmp_num).find( '2017' ) = = - 1 and str (tmp_num).find( '2016' ) = = - 1 : not_date_columns.append(column) return data[not_date_columns] # 去掉object、int类型的列 def drop_non_number(data): data_types = data.dtypes.reset_index() data_types.columns = [ 'col' , 'dtype' ] data_object = data_types[data_types.dtype = = 'object' ].col.values data_object = data[data_object] data_object.to_csv( 'non_number.csv' ,index = False ) col_val = data_types[data_types.dtype = = 'float64' ].col.values return data[col_val] |
四、类别特征与类别特征
1.卡方检验
思想:
- 先假设两个变量确实是独立的(“原假设”),然后观察实际值(观察值)与理论值(这个理论值是指“如果两者确实独立”的情况下应该有的值)的偏差程度,如果偏差足够小,我们就认为误差是很自然的样本误差,是测量手段不够精确导致或者偶然发生的,两者确确实实是独立的,此时就接受原假设;如果偏差大到一定程度,使得这样的误差不太可能是偶然产生或者测量不精确所致,我们就认为两者实际上是相关的,即否定原假设,而接受备择假设.
- 这个式子就是卡方检验使用的差值衡量公式。当提供了数个样本的观察值x1,x2,…xi,…xn之后,代入到式中就可以求得开方值,用这个值与事先设定的阈值比较,如果大于阈值(即偏差很大),就认为原假设不成立,反之则认为原假设成立。
使用方法:
- 特征为连续型,可将其分箱,变成有序的类别型特征,然后和label计算卡方值;如果特征为类别型,不需要one-hot
- 步骤:
- 步骤1:做出H0,H1这对互斥的假设,计算出H0为真时的期望值,统计出实际的观测值,通过期望值和观测值求得chi-square(卡方),再通过卡方查表(知道自由度和alpha),得到p值。
- 步骤2:根据p值与α(1-置信度)的比较,如果p-value<α,则拒绝(reject)H0,推出H1成立;如果p-value>α,则接受(accpet)H0,推出H1不成立。
- p值?为什么小于0.05就很重要?p值的作用?
- p值可通过计算chi-square后查询卡方分布表得出,用于判断H0假设是否成立的依据。
- 大部分时候,我们假设错误拒绝H0的概率为0.05,所以如果p值小于0.05,说明错误拒绝H0的概率很低,则我们有理由相信H0本身就是错误的,而非检验错误导致。大部分时候p-value用于检验独立变量与输入变量的关系,H0假设通常为假设两者没有关系,所以若p值小于0.05,则可以推翻H0(两者没有关系),推出H1(两者有关系)。
- 当p值小于0.05时,我们就说这个独立变量重要(significant),因为这个独立变量与输出结果有关系。
- p-value就是用来判断H0假设是否成立的依据。因为期望值是基于H0假设得出的,如果观测值与期望值越一致,则说明检验现象与零假设越接近,则越没有理由拒绝零假设。如果观测值与期望值越偏离,说明零假设越站不住脚,则越有理由拒绝零假设,从而推出对立假设的成立。
- sklearn使用方法
- sklearn源码
1 2 3 4 5 6 7 8 9 | sklearn.feature_selection.chi2(X, y) 参数: X:{array - like,sparse matrix} shape = (n_samples,n_features) y:{array - like} shape = (n_samples,) 返回: chi2:array,shape = (n_features,) 每个特征的卡方统计数据 pval:array,shape = (n_features,) 每个特征的p值 算法时间复杂度O(n_classes * n_features) |
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | non_neg_cate_feats = [ 'cardIndex' , 'downNetwork' , 'signalStrengthNum' , 'signalQualityNum' , 'mostGridLTE' , 'mostGridLTEPlus' , 'signalPerformanceADDNum' , 'signalPerformanceDIVNum' , 'signalPerformanceMULNum' ] # 卡方检验 用来检验两个样本or变量是否独立 from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 X, y = offline_data_shuffle[non_neg_cate_feats], offline_data_shuffle.label select_k_best = SelectKBest(chi2, k = 6 ) # scores按升序排序,选择排前k名所对应的特征 X_new = select_k_best.fit_transform(X, y) X_new.shape p_scores = zip (select_k_best.scores_,select_k_best.pvalues_) dict_p_scores = dict ( zip (non_neg_cate_feats,p_scores)) >>> sorted (dict_p_scores.items(),key = lambda x:x[ 1 ],reverse = False ) [( 'signalQualityNum' , ( 0.0047487364247874265 , 0.9450604019371723 )), ( 'cardIndex' , ( 0.42794079034586147 , 0.5130011047102445 )), ( 'downNetwork' , ( 4.232840836040372 , 0.039649024714896966 )), ( 'mostGridLTEPlus' , ( 22.54372206267445 , 2.0541471820820565e - 06 )), ( 'signalPerformanceADDNum' , ( 83.2781756776784 , 7.128224882894165e - 20 )), ( 'mostGridLTE' , ( 108.06852404196152 , 2.596443689456046e - 25 )), ( 'signalPerformanceDIVNum' , ( 114.25902772721962 , 1.1435127027103025e - 26 )), ( 'signalPerformanceMULNum' , ( 118.46298229427805 , 1.3729262834830412e - 27 )), ( 'signalStrengthNum' , ( 176.53365084245885 , 2.768884720816111e - 40 ))] results_indexs = select_k_best.get_support( True ) results = [non_neg_cate_feats[idx] for idx in results_indexs] # 卡方检验选出的6个特征 >>> print (results) [ 'signalStrengthNum' , 'mostGridLTE' , 'mostGridLTEPlus' , 'signalPerformanceADDNum' , 'signalPerformanceDIVNum' , 'signalPerformanceMULNum' ] 卡方检验的结果显示: p值小于 0.05 ,说明拒绝原假设(原假设特征与label是独立的) signalQualityNum、cardIndex与label是独立的; [ 'signalStrengthNum' , 'mostGridLTE' , 'mostGridLTEPlus' , 'signalPerformanceADDNum' , 'signalPerformanceDIVNum' , 'signalPerformanceMULNum' ]与label相关 |
2.Fisher得分
对于分类而言,好的特征应该是在同一个类别中的取值比较相似,而在不同类别之间的取值差异比较大;fisher得分越高,特征在不同类别中的差异性越大,在同一类别中的差异性越小,则特征越重要。
3.F检验
作用: 用来判断特征与label的相关性的,F 检验只能表示线性相关关系
4.斯皮尔曼等级相关(分类,类别型与类别型)
特征为类别型,标签为类别型
Spearman秩相关系数:是度量两个变量之间的统计相关性的指标,用来评估当前单调函数来描述俩个变量之间的关系有多好。
在没有重复数据的情况下,如果一个变量是另一个变量的严格单调函数,二者之间的spearman秩相关系数就是1或+1 ,称为完全soearman相关.
如果其中一个变量增大时,另一个变量也跟着增大时,则spearman秩相关系数时正的
如果其中一个变量增大时,另一个变量却跟着减少时,则spearman秩相关系数时负的
如果其中一个变量变化时,另一个变量没有变化,spearman秩相关系为0
随着两个变量越来越接近严格单调函数时,spearman秩相关系数在数值上越来越大。
假设:
Spearman等级相关性测试对于分布没有做任何假设。Spearman rho相关的假设是数据必须至少是序数,一个变量上的分数必须与其他变量单调相关。
.10和.29之间表示小关联;
.30和.49之间;
.50及以上的系数表示大的关联或关系
有序量表对待测量的项目进行排序,以指示它们是否具有更多,更少或相同量的被测量变量。序数量表使我们能够确定X> Y,Y> X,或者如果X = Y。一个例子是排序舞蹈比赛的参与者。排名第一的舞者是比排名第二的舞者更好的舞者。排名第二的舞者是比排名第三的舞者更好的舞者,等等。虽然这个规模使我们能够确定大于,小于或等于,但它仍然没有定义单位之间关系的大小。
5.Kendall(肯德尔等级)相关系数(分类)
特征为类别型,标签为类别型
肯德尔相关系数是一个用来测量两个随机变量相关性的统计值。
一个肯德尔检验是一个无参数假设检验,检验两个随机变量的统计依赖性。
肯德尔相关系数的取值范围在-1到1之间,
当τ为1时,表示两个随机变量拥有一致的等级相关性;当τ为-1时,表示两个随机变量拥有完全相反的等级相关性;
当τ为0时,表示两个随机变量是相互独立的。
6.互信息和最大互系数(非参数)
(1)互信息
作用:估计类别特征与label之间的相关性,互信息是非负值。当且仅当两个特征是独立的,它等于0,而更高的值意味着更高的依赖性。
使用方法:
在sklearn中,可以使用mutual_info_classif(分类)和mutual_info_regression(回归)来计算各个输入特征和输出值之间的互信息。使用feature_selection库的SelectKBest类结合最大信息系数法来选择特征
sklearn.feature_selection.mutual_info_classif(X, y, discrete_features=’auto’, n_neighbors=3, copy=True, random_state=None)
参数:
X:shape = (n_samples,n_features)
y:shape = (n_samples)
discrete_features: {'auto',bool,array_like},默认='auto'
n_neighbors:int,默认=3,用于连续变量的MI估计的邻居数量,较高的值会减少估算的方差,但是可能引入偏差
copy:bool,默认=True,是否复制给定数据,如果设置为False,则初始数据将被覆盖
random_state:int,RandomState实例或None,可选,默认=None,伪随机数发生器的种子,用于向连续变量添加小噪声以去除重复值。 如果是int,则random_state是随机数生成器使用的种子; 如果是RandomState实例,则random_state是随机数生成器; 如果为None,则随机数生成器是`np.random`使用的RandomState实例。
返回:
mi:ndarray,shape=(n_features)每个特征与目标之间的互信息
举例:
X, y = data[features], data.label # 互信息 from sklearn.feature_selection import mutual_info_classif mutual_info_classif(X,y)
卡方检验和互信息的区别
卡方检验对于出现次数较少的特征更容易给出高分。例如某一个特征就出现过一次在分类正确的数据中,则该特征会得到相对高的分数,而互信息则给分较低。其主要原因还是由于互信息在外部乘上了一个该类型出现的概率值,从而打压了出现较少特征的分数。
(2)最大信息系数
想把互信息直接用于特征选择其实不是太方便,因为它不属于度量方式,也没有办法归一化,在不同数据及上的结果无法做比较;对于连续变量的计算不是很方便(X和 Y 都是集合, xi,y都是离散的取值),通常变量需要先离散化,而互信息的结果对离散化的方式很敏感。
最大信息系数克服了这两个问题。它首先寻找一种最优的离散化方式,然后把互信息取值转换成一种度量方式,MIC值越大,两个特征间的相似程度越高。minepy提供了MIC功能。
MIC计算三步骤:参考
给定i、j,对XY构成的散点图进行i列j行网格化,并求出最大的互信息值
对最大的互信息值进行归一化
选择不同尺度下互信息的最大值作为MIC值
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import numpy as np from minepy import MINE from numpy import array from sklearn.feature_selection import SelectKBest def mic(x, y): m = MINE() m.compute_score(x, y) return (m.mic(), 0.5 ) # 选择 K 个最好的特征,返回特征选择后的数据 mic_select = SelectKBest( lambda X,y: tuple ( map ( tuple ,array( list ( map ( lambda x:mic(x, y), X.T))).T)), k = 10 ) X_new = mic_select.fit_transform(X,y) # k个最好的特征在原特征中的索引 mic_results_indexs = mic_select.get_support( True ) # 得分 mic_scores = mic_select.scores_ # 特征与最大信息系数的对应 mic_results = [(features[idx],mic_scores[idx]) for idx in mic_results_indexs] mic_results |
7.距离相关系数
好的特征子集应该使得属于同一类的样本距离尽可能小,属于不同类的样本之间的距离尽可能远。同样基于此种思想的有fisher判别分类反法。常用的距离度量(相似性度量)包括欧氏距离、标准化欧氏距离、马氏距离等。
距离相关系数是为了克服Pearson相关系数的弱点而生的。在 和
这个例子中,即便Pearson相关系数是
,我们也不能断定这两个变量是独立的(有可能是非线性相关);但如果距离相关系数是
,那么我们就可以说这两个变量是独立的。
五、数值特征与类别特征
1.数值特征离散化
将数值特征离散化,然后,使用类别与类别变量相关性分析的方法来分析相关性。
2.箱形图
使用画箱形图的方法,看类别变量取不同值,数值变量的均值与方差及取值分布情况。
如果,类别变量取不同值,对应的数值变量的箱形图差别不大,则说明,类别变量取不同值对数值变量的影响不大,相关性不高;反之,相关性高。
3.Relief(Relevant Features)
Relief 借用了“假设间隔”(hypothesis marginhypothesis margin)的思想,我们知道在分类问题中,常常会采用决策面的思想来进行分类,“假设间隔”就是指在保持样本分类不变的情况下,决策面能够移动的最大距离
当一个属性对分类有利时,则该同类样本在该属性上的距离较近(第一项越小),异常样本在该类属性上的距离较远(第二项越大),则该属性对分类越有利。
假设数据集D为(x1,y1),(x2,y2),...,(xm,ym),对每个样本xi,计算与xi同类别的最近邻xi,nh,称为是“猜中近邻”(near-heat),然后计算与xi非同类别的最近邻xi,nm,称为是“猜错近邻”(near-miss),具体点我
对离散型特征:
对连续型特征:
适用场景:二分类
举例:二分类
4.Relief-F
适用场景:多分类
参考文献:
【3】P值解释和误区
【5】Maximal Information Coefficient (MIC)最大互信息系数详解与实现
【6】结合Scikit-learn介绍几种常用的特征选择方法
【7】Sklearn中的f_classif和f_regression
【8】特征选择:方差选择法、卡方检验、互信息法、递归特征消除、L1范数、树模型
【9】结合Scikit-learn介绍几种常用的特征选择方法(优秀)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!