特征选择:概述与方法
不知各位读者是否遇到这种情形:在一项机器学习工作中,千方百计地变换模型并调整参数,但收效甚微;后经高人指点,对进入模型的特征做了一些修改后,即使用了最基础的模型,其效果也有如脱胎换骨。这似乎在暗示我们,在机器学习任务中,“使用什么样的特征”往往要比“使用什么样的模型”更重要。
以大数据的普遍流行为分割线,无论是在之前的数据因稀少而珍贵的时代,还是现在的数据「泛滥」时代,选择特征一直都是机器学习研究者所关注的重要内容。数据少的时候,人们希望通过增加特征来找到目标变量的变化趋势;数据多的时候,人们希望剔除冗余和无关因素的影响来加速模型收敛,提升模型精度。
下面,我将以scikit-learn
中的相关方法为例,梳理特征选择的基本理论。
特征选择:概述与方法
特征选择,顾名思义,就是从所有给定的特征中选出一个或多个用于构建模型。为了评估选出的特征是否让模型具有了更好的表现效果,还需要定义评价指标来对特征子集进行打分。
进行特征选择的一个最直观的想法是,穷举特征的所有组合,分别进行评价。虽然这种方法在理论上能够获得最优的组合,但对于高维数据而言,会面临组合爆炸的问题,不太可行。为了提高可行性,我们需要采用其他的方式来选择特征。
基于方差的特征选择
方差是衡量数据离散程度的指标,值越小说明数据变化的程度越小。举一个极端的例子,如果数据集中的某个特征的方差为0,说明该特征的取值在所有样本中都是一致的,那么它对于我们区分目标变量毫无帮助,是可以剔除的。
一般的,我们可以设置一个方差阈值,然后将每个特征的方差与阈值进行比较。如果某特征的方差低于该阈值,则认为该特征的数据变化不大,并推断其所包含的信息不足以对目标变量进行区分,因而予以剔除。
下面是一个sklearn中的例子:
>>> from sklearn.feature_selection import VarianceThreshold
>>> X = [[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 1, 1]]
>>> sel = VarianceThreshold(threshold=(.8 * (1 - .8)))
>>> sel.fit_transform(X)
array([[0, 1],[1, 0],[0, 0],[1, 1],[1, 0],[1, 1]])
易知,X
的第一个维度的方差不满足阈值要求,该特征被剔除。
读者应该已经发现,这种做法是有「问题」的:在上面的例子中,如果目标变量的取值刚好与第一个特征的取值变化相同,换句话说,它们具有很高的相关性,这时剔除该特征是不合适的。
这种问题的本质,在于判定哪些变量需要剔除时没有考虑目标变量的取值。因此,它是一种相对粗糙的方法,多用于特征初筛,剔除那些在我们看来几乎绝对不可能提升模型效果的特征。
相关系数法
以回归问题为例对本方法及下一个方法进行说明。
要衡量某个特征对于目标的预测是否重要,一个直观的想法是计算特征与目标的相关性。例如,可以计算特征列与目标列的皮尔逊相关系数:
from sklearn.datasets import load_boston # 波士顿房价数据集,在1.2版本后将不再可用
X, y = load_boston(return_X_y=True)
print(X.shape)
# 输出:(506, 13)
# 样本数为506,特征数为13
from sklearn.feature_selection import r_regression
print(r_regression(X, y))
# 输出:
# [-0.38830461 0.36044534 -0.48372516 0.17526018 -0.42732077 0.69535995
# -0.37695457 0.24992873 -0.38162623 -0.46853593 -0.50778669 0.33346082
# -0.73766273]
r_regression
实际上计算的是各个特征与y
的相关系数,可以验证如下:import numpy as np; print(np.corrcoef(X[:,0], y)[0][1]) # 得到第一个特征与y的相关系数,可以类似地得到其他特征的相关系数
接下来,可以将相关系数从大到小进行排序,从而选择前k
个最相关的特征用于建模。sklearn
已经帮我们实现了这个过程:
from sklearn.feature_selection import SelectKBestk = 3 # 这里选择前3个最相关的特征
selector = SelectKBest(r_regression, k=3) # r_regression就是评分函数
X_new = selector.fit_transform(X, y)
print(selector.get_feature_names_out())
# 输出:['x1', 'x5', 'x11']
可以看出,经过r_regression
评分,选择出的三个最可能影响目标的特别分别是x1
、x5
和x11
,即原始X
的第2、6和12列。
由于X是numpy数组,没有列名,因此sklearn自动生成了列名。如果传入的X是pandas.DataFrame,那么
get_feature_names_out
将会输出X的列名。
R2R^2R2与FFF统计量
在使用相关系数进行特征选择时,某些特征与目标的负相关程度很高,也可以用于建模预测,但有可能会被遗漏;此外,多重共线性问题也是相关系数法所无法避免的。为此,需要一些改进的方法。
我们知道,判定系数R2R^2R2可以用来衡量所建立的回归模型的“好坏”,其计算公式如下:
R2=SSE/SST=1−SSRSSTR^2=SSE/SST=1-\frac{SSR}{SST} R2=SSE/SST=1−SSTSSR
其中,称SST为总平方和(total sum of squares)、SSE为解释平方和(explained sum of squares)、SSR为残差平方和(residual sum of squares)。它们各自的定义如下:
SST=∑i=1n(yi−yˉ)2SST=\sum_{i=1}^{n}(y_i-\bar y)^2SST=∑i=1n(yi−yˉ)2
SSE=∑i=1n(y^i−yˉ)2SSE=\sum_{i=1}^{n}(\hat y_i-\bar y)^2SSE=∑i=1n(y^i−yˉ)2
SSR=∑i=1n(yi−y^i)2SSR=\sum_{i=1}^{n}(y_i-\hat y_i)^2SSR=∑i=1n(yi−y^i)2
下图有助于理解上述三个概念:
SST度量了yiy_iyi的总样本波动,反映了样本观测值总体离差的大小;SSE度量了yi^\hat {y_i}yi^的样本波动,反映由模型中解释变量所解释的那部分离差的大小;SSR度量了残差的样本波动,反映观测值与估计值偏离的程度,也是解释变量未解释的那部分离差的大小。
它们之间有如下关系:SST=SSR+SSESST=SSR+SSESST=SSR+SSE(证明略)。因此可以知道,SSE不可能大于SST,所以R2R^2R2的取值范围为[0,1][0,1][0,1]。越接近于1,说明模型的拟合得越好。
还有一个困扰人的问题:判定系数表示为R2R^2R2,那么是否说明它就等于相关系数rrr的平方呢?
对于简单线性回归而言,上述结论是正确的;否则,就是不正确的。
我们知道,两个卡方分布分别除以其自由度后构造的新的统计量就服从F分布。这里先说结论:在线性回归分析中,有SSR∼χ(1)SSR \sim \chi(1)SSR∼χ(1),SSE∼χ(n−2)SSE \sim \chi(n-2)SSE∼χ(n−2)。因此:
F(1,n−2)=SSRSSE/(n−2)=SSR/SSTSSE/SST∗(n−2)=R21−R2∗(n−2)F(1,n-2)=\frac{SSR}{SSE/(n-2)}=\frac{SSR/SST}{SSE/SST}*(n-2)=\frac{R^2}{1-R^2}*(n-2) F(1,n−2)=SSE/(n−2)SSR=SSE/SSTSSR/SST∗(n−2)=1−R2R2∗(n−2)
在简单线性回归中,又有R2=r2R^2=r^2R2=r2,所以:
F(1,n−2)=r21−r2∗(n−2)F(1,n-2)=\frac{r^2}{1-r^2}*(n-2) F(1,n−2)=1−r2r2∗(n−2)
这也就意味着,如果知道了自变量和因变量的相关系数,就可以求出其F统计量的值,从而判定该自变量在回归模型中是否具有解释力。
在sklearn中,可以用f_regression
来作为评价函数进行特征选择:
from sklearn.feature_selection import f_regressionselector = SelectKBest(f_regression, k=3)
X_new = selector.fit_transform(X, y)
print(selector.get_feature_names_out())
# 输出:['x5', 'x10', 'x12']
可以看出,经过f_regression
选择后,得出的三个最能解释因变量的为第5、10和12个特征。
执行以下代码,以获得各个特征对因变量的解释力的F统计量值:
print(f_regression(X, y))
# array([ 89.48611476, 75.2576423 , 153.95488314, 15.97151242,
# 112.59148028, 471.84673988, 83.47745922, 33.57957033,
# 85.91427767, 141.76135658, 175.10554288, 63.05422911,
# 601.61787111]),
# array([1.17398708e-19, 5.71358415e-17, 4.90025998e-31, 7.39062317e-05,
# 7.06504159e-24, 2.48722887e-74, 1.56998221e-18, 1.20661173e-08,
# 5.46593257e-19, 5.63773363e-29, 1.60950948e-34, 1.31811273e-14,
# 5.08110339e-88])
第一个array为各个因变量的F统计量值,可以看出,SelectKBest
实际上是选出了具有最大F值的前3个特征;第二个array为对应的p值。读者可以利用相关系数自行验证F统计量的值是否满足F=r2/(1−r2)∗(n−2)F=r^2/(1-r^2)*(n-2)F=r2/(1−r2)∗(n−2)。
参考内容:
- https://stats.stackexchange.com/questions/56881/whats-the-relationship-between-r2-and-f-test
- 特征选择
- R2R^2R2:Calculation & Interpretation
- F检验
- 残差平方和SSE为什么服从卡方分布?
特征选择:概述与方法相关推荐
- 文本分类——特征选择概述
内容提要 特征选择概述 常见模型 文档频率(DF) 卡方校验(CHI) 信息增益(IG) 互信息(MI) 特征选择概述 在向量空间模型中,文本可以选择字.词组.短语.甚至"概念" ...
- matlab 特征降维方法,降维和特征选择的关键方法介绍及MATLAB实现
目录 概念理解 降维: 特征选择: 降维的方法 主成分分析(Principle Component Analysis, PCA)方法 偏最小二乘法(Partial Least Squares, PLS ...
- 机器学习中,有哪些特征选择的工程方法?
机器学习中,有哪些特征选择的工程方法? 数据和特征决定了机器学习的上限,而模型和算法调参只是逼近这个上限而已. 0,特征本身是否具有基础的表征能力或者判别性,例如方差筛选法.方差是衡量一个变量的离散程 ...
- System类的概述和方法使用
System类的概述和方法使用 System类的概述 Java.lang包下的,父类object类,被final类修饰, System 类包含一些有用的类字段和方法.它不能被实例化.(私有了构造方法) ...
- java date的使用_java:Date类的概述和方法使用
* A:Date类的概述 * 类 Date 表示特定的瞬间,精确到毫秒. * B:构造方法 * public Date() * public Date(long date) * C:成员方法 * pu ...
- 详细介绍Python中的“魔术方法“__XXX___; 概述__str__()方法;__new__()方法; 三. __ new__ 和__init__的区别
概述 一.__str__方法 当不用__str__()时: 发现输出结果只有对象一串id地址信息; 当我们想打印出更多信息时,用__str__()方法; 二.new()方法 三. __ new__ 和 ...
- 特征选择的工程方法?
特征选择是特征工程中的重要问题(另一个重要的问题是特征提取),坊间常说:**数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已.**由此可见,特征工程尤其是特征选择在机器学习中占有相当重 ...
- Request和Response的概述及其方法
Request和Response的概述 Request是请求对象,Response是响应对象 ServletRequest和HttpServletRequest是继承关系,并且两个都是接口,接口是无法 ...
- 机器学习中特征选择概述
1. 背景 1.1 问题 在机器学习的实际应用中,特征数量可能较多,其中可能存在不相关的特征,特征之间也可能存在相关性,容易导致如下的后果: (1) 特征个数越多,分析特征.训练模型所需的时间就越长, ...
最新文章
- .net2.0中SqlBulkCopy批量复制数据出错原因分析!
- gm怎么刷东西 rust_Rust语言:解引用详述,搞不明白这个概念,趁早放弃Rust
- 数据结构--红黑树 Red Black Tree
- JadClipse反编译工具在MyEclipse中的安装(先看Eclipse的配置方式)
- Front End Developer Questions 前端开发人员问题(二)
- 计算机视觉基础:自适应阈值分割(Computer Vision Fundamentals: Adaptive Threshold Segmentation)
- java实现视频在线播放并解决java.io.IOException: 您的主机中的软件中止了一个已建立的连接。
- php常用函数最全总结
- BTA分论坛现场直击 | 区块链行业应用有待落地,游戏上链冰火两重天
- mysql8不区分大小写_不看不知道,这年头学个字母都有这么多门道(附学习资源)...
- medusa 使用教程
- 基于一阶倒立摆系统的模糊神经网络PID控制
- Spring Boot---(10)SpringBoot整合RabbitMQ
- 客户端呼叫Flash Medis Server3服务端入门
- Contrastive Learning Rivals Masked Image Modeling in Fine-tuning via Feature Distillation
- B. Partial Replacement
- 魏小亮:如何选择硅谷的IT公司
- 监控系统cat安装和配置demo ubuntu 14.04
- UNIX文件系统下误删除的数据恢复经典案例--UFS删除恢复
- js文件流,导出txt