不知各位读者是否遇到这种情形:在一项机器学习工作中,千方百计地变换模型并调整参数,但收效甚微;后经高人指点,对进入模型的特征做了一些修改后,即使用了最基础的模型,其效果也有如脱胎换骨。这似乎在暗示我们,在机器学习任务中,“使用什么样的特征”往往要比“使用什么样的模型”更重要

以大数据的普遍流行为分割线,无论是在之前的数据因稀少而珍贵的时代,还是现在的数据「泛滥」时代,选择特征一直都是机器学习研究者所关注的重要内容。数据少的时候,人们希望通过增加特征来找到目标变量的变化趋势;数据多的时候,人们希望剔除冗余和无关因素的影响来加速模型收敛,提升模型精度。

下面,我将以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评分,选择出的三个最可能影响目标的特别分别是x1x5x11,即原始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为什么服从卡方分布?

特征选择:概述与方法相关推荐

  1. 文本分类——特征选择概述

    内容提要 特征选择概述 常见模型 文档频率(DF) 卡方校验(CHI) 信息增益(IG) 互信息(MI) 特征选择概述   在向量空间模型中,文本可以选择字.词组.短语.甚至"概念" ...

  2. matlab 特征降维方法,降维和特征选择的关键方法介绍及MATLAB实现

    目录 概念理解 降维: 特征选择: 降维的方法 主成分分析(Principle Component Analysis, PCA)方法 偏最小二乘法(Partial Least Squares, PLS ...

  3. 机器学习中,有哪些特征选择的工程方法?

    机器学习中,有哪些特征选择的工程方法? 数据和特征决定了机器学习的上限,而模型和算法调参只是逼近这个上限而已. 0,特征本身是否具有基础的表征能力或者判别性,例如方差筛选法.方差是衡量一个变量的离散程 ...

  4. System类的概述和方法使用

    System类的概述和方法使用 System类的概述 Java.lang包下的,父类object类,被final类修饰, System 类包含一些有用的类字段和方法.它不能被实例化.(私有了构造方法) ...

  5. java date的使用_java:Date类的概述和方法使用

    * A:Date类的概述 * 类 Date 表示特定的瞬间,精确到毫秒. * B:构造方法 * public Date() * public Date(long date) * C:成员方法 * pu ...

  6. 详细介绍Python中的“魔术方法“__XXX___; 概述__str__()方法;__new__()方法; 三. __ new__ 和__init__的区别

    概述 一.__str__方法 当不用__str__()时: 发现输出结果只有对象一串id地址信息; 当我们想打印出更多信息时,用__str__()方法; 二.new()方法 三. __ new__ 和 ...

  7. 特征选择的工程方法?

    特征选择是特征工程中的重要问题(另一个重要的问题是特征提取),坊间常说:**数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已.**由此可见,特征工程尤其是特征选择在机器学习中占有相当重 ...

  8. Request和Response的概述及其方法

    Request和Response的概述 Request是请求对象,Response是响应对象 ServletRequest和HttpServletRequest是继承关系,并且两个都是接口,接口是无法 ...

  9. 机器学习中特征选择概述

    1. 背景 1.1 问题 在机器学习的实际应用中,特征数量可能较多,其中可能存在不相关的特征,特征之间也可能存在相关性,容易导致如下的后果: (1) 特征个数越多,分析特征.训练模型所需的时间就越长, ...

最新文章

  1. .net2.0中SqlBulkCopy批量复制数据出错原因分析!
  2. gm怎么刷东西 rust_Rust语言:解引用详述,搞不明白这个概念,趁早放弃Rust
  3. 数据结构--红黑树 Red Black Tree
  4. JadClipse反编译工具在MyEclipse中的安装(先看Eclipse的配置方式)
  5. Front End Developer Questions 前端开发人员问题(二)
  6. 计算机视觉基础:自适应阈值分割(Computer Vision Fundamentals: Adaptive Threshold Segmentation)
  7. java实现视频在线播放并解决java.io.IOException: 您的主机中的软件中止了一个已建立的连接。
  8. php常用函数最全总结
  9. BTA分论坛现场直击 | 区块链行业应用有待落地,游戏上链冰火两重天
  10. mysql8不区分大小写_不看不知道,这年头学个字母都有这么多门道(附学习资源)...
  11. medusa 使用教程
  12. 基于一阶倒立摆系统的模糊神经网络PID控制
  13. Spring Boot---(10)SpringBoot整合RabbitMQ
  14. 客户端呼叫Flash Medis Server3服务端入门
  15. Contrastive Learning Rivals Masked Image Modeling in Fine-tuning via Feature Distillation
  16. B. Partial Replacement
  17. 魏小亮:如何选择硅谷的IT公司
  18. 监控系统cat安装和配置demo ubuntu 14.04
  19. UNIX文件系统下误删除的数据恢复经典案例--UFS删除恢复
  20. js文件流,导出txt

热门文章

  1. 一 企业信息化战略和实施
  2. 数据库_01_增删改
  3. 常用计算机设备教案,初中信息技术《导购电脑设备》教案
  4. 纪念 Dan Kohn 先生
  5. Hazel引擎学习(五)
  6. STM32CubeMx开发之路—LTDC驱动STM32F429I-Discover上的显示屏
  7. 洛谷· [AHOI2008]紧急集合 / 聚会
  8. JavaScript--简单案例
  9. Word文件如何进行关键词查询
  10. html实现文本的查找与替换,在 InDesign 中查找并替换文本