专栏首页数据STUDIO特征选择与提取最全总结之过滤法

特征选择与提取最全总结之过滤法


特征抽取是数据挖掘任务最为重要的一个环节,一般而言,它对最终结果的影响要高过数据挖掘算法本身。

不幸的是,关于怎样选取好的特征,还没有严格、快捷的规则可循,其实这也是数据挖掘科学更像是一门艺术的所在。

创建好的规则离不开直觉,还需要专业领域知识和数据挖 掘经验,光有这些还不够,还得不停地尝试、摸索,在试错中前进,有时多少还要靠点运气。

通常特征数量很多,但我们只想选用其中一小部分。有如下几个原因。

1、降低复杂度

随着特征数量的增加,很多数据挖掘算法需要更多的时间和资源。减少特征数量,是提高算法运行速度,减少资源使用的好方法。

2、降低噪音

增加额外特征并不总会提升算法的表现。额外特征可能扰乱算法的正常工作,这些额外特征间的相关性和模式没有实际应用价值(这种情况在小数据集上很常见)。只选择合适的特征有助于减少出现没有实际意义的相关性的几率。

3、增加模型可读性

根据成千上万个特征创建的模型来解答一个问题,对计算机来说很容易,但模型对我们自己来说就晦涩无比。因此,使用更少的特征,创建我们自己可以理解的模型,就很有必要。

有些分类算法确实很强壮,能够处理噪音问题,特征再多也不在话下,但是选用干净的数据,选取更具描述性的特征,对算法效果提升很有帮助。

根据特征选择的形式又可以将特征选择方法分为三种

Filter:过滤法,按照发散性或者相关性对各个特征进行评分,设定阈值或者待选择阈值的个数,选择特征。

Wrapper:包装法,根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征。

Embedded:嵌入法,先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。类似于Filter方法,但是是通过训练来确定特征的优劣。

写在前面

为了帮助更好地理解特征选择,这里使用我们常用的股市数据作为基础数据。

由于文章较长,为方便阅读,我将特征选择与特征提取总结文章拆分为上下两篇,上篇(本文)主要内容包括如下图所示,主要介绍过滤法中常用的几种特征选择方法

导入相关模块

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
import yfinance as yf
yf.pdr_override()

获取数据

仍然用腾讯股市数据,辅助理解本文内容。

symbol = 'TCEHY'
start = '2016-01-01'
end = '2021-01-01'
df = yf.download(symbol, start, end)
# df = df.reset_index()
# View columns 
df.head()

特征构造

dataset = df.copy()
['Increase_Decrease'] = np.where(dataset['Volume'].shift(-1) > dataset['Volume'],1,0)
dataset['Buy_Sell_on_Open'] = np.where(dataset['Open'].shift(-1) > dataset['Open'],1,0)
dataset['Buy_Sell'] = np.where(dataset['Adj Close'].shift(-1) > dataset['Adj Close'],1,0)
dataset['Returns'] = dataset['Adj Close'].pct_change()
dataset = dataset.dropna()
dataset.head()

数据准备

设定目标标签为收盘价,研究哪些变量对收盘价影响加大。通过一定对方法剔除几乎没有影响的特征,选出影响较多对特征。特征选择在维度较大时尤为重要。

features = dataset.drop(['Adj Close', 'Close', 'Returns'], axis=1)
array = features.values
X = array.astype(int)

Y = dataset['Adj Close'].values.astype(int)

过滤法

过滤方法通常用作预处理步骤,特征选择完全独立于任何机器学习算法。它是根据各种统计检验中的分数以及相关性的各项指标来选择特征。

方差过滤

这是通过特征本身的方差来筛选特征的类。比如一个特征本身的方差很小,就表示样本在这个特征上基本没有差异,可能特征中的大多数值都一样,甚至整个特征的取值都相同,那这个特征对于样本区分没有什么作用。

scikit-learn中的VarianceThreshold转换器可用来删除特征值的方差达不到最低标准的特征。

from sklearn.feature_selection import VarianceThreshold
vt = VarianceThreshold()
vt.fit_transform(X)
var_thd = pd.DataFrame(vt.variances_, columns = ["Variance"], index=features.columns)
var_thd = var_thd.reset_index()
var_thd.sort_values('Variance',ascending=0)

无论什么时候,拿到数据后,先做下类似简单、直接的分析,对数据集的特点做到心中有数。方差为0的特征不但对数据挖掘没有丝毫用处,相反还会拖慢算法的运行速度。

单变量选择

单变量的特征选择是通过基于一些单变量的统计度量方法来选择最好的特征。属于过滤法的一种。

scikit-learn提供了几个用于选择单变量特征的转换器,其中SelectKBest返回

k

个最佳特征,SelectPercentile返回表现最佳的前

r%

个特征。这两个转换器都提供计算特征表现的一系列方法。都将得分函数作为输入,返回单变量的得分和p值。可作为输入的评分函数有:

  • 对于回归: f_regression , mutual_info_regression, 互信息
  • 对于分类: chi2 , f_classif , mutual_info_classif, 皮尔森相关系数

SelectKBest 选择出前k个与标签最相关的特征,主要有两个参数: 1、score_func : callable,函数取两个数组X和y,返回一对数组(scores, pvalues)或一个分数的数组。默认函数为f_classif,默认函数只适用于分类函数。 2、k:int or "all", optional, default=10。所选择的topK个特征。“all”选项则绕过选择,用于参数搜索。

卡方

单个特征和某一类别之间相关性的计算方法有很多。最常用的有卡方检验。经典的卡方检验是检验定性自变量对定性因变量的相关性。

卡方过滤是专门针对离散型标签(即分类问题)的相关性过滤。卡方检验类 feature_selection.chi2 计算每个非负特征和标签之间的卡方统计量,并依照卡方统计量由高到低为特征排名。

再结合 feature_selection.SelectKBest 这个可以输入”评分标准“来选出前K个分数最高的特征的类,我们可以借此除去最可能独立于标签,与我们分类目的无关的特征。

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

# 再使用SelectKBest转换器类,用卡方函数打分,初始化转换器。
test = SelectKBest(score_func=chi2, k=3)
test.fit(X, Y)

# 得分情况
np.set_printoptions(precision=3)
print(test.scores_)
[6.365e+03 6.416e+03 6.286e+03 8.295e+08 
 2.949e+01 2.240e+01 3.059e+01]

卡方检验的本质是推测两组数据之间的差异,其检验的原假设是”两组数据是相互独立的”。卡方检验返回卡方值和P值两个统计量,其中卡方值很难界定有效的范围,而p值,我们一般使用0.01或0.05作为显著性水平,即p值判断的边界。

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

F检验

另外类似的方法还有F检验,又称ANOVA,方差齐性检验,是用来捕捉每个特征与标签之间的线性关系的过滤方法。它即可以做回归也可以做分类,因此包含feature_selection.f_classif(F检验分类)和feature_selection.f_regression(F检验回归)两个类。其中F检验分类用于标签是离散型变量的数据,而F检验回归用于标签是连续型变量的数据。

F检验的本质是寻找两组数据之间的线性关系,其原假设是”数据不存在显著的线性关系“。它返回F值和p值两个统 计量。

和卡方过滤一样,我们希望选取p值小于0.05或0.01的特征,这些特征与标签时显著线性相关的,而p值大于 0.05或0.01的特征则被我们认为是和标签没有显著线性关系的特征,应该被删除。

互信息

互信息法是用来捕捉每个特征与标签之间的任意关系(包括线性和非线性关系)的过滤方法。和F检验相似,它既可以做回归也可以做分类,并且包含两个类 feature_selection.mutual_info_classif(互信息分类)和feature_selection.mutual_info_regression(互信息回归)。这两个类的用法和参数都和F检验一模一样,不过互信息法比F检验更加强大,F检验只能够找出线性关系,而互信息法可以找出任意关系。

互信息法不返回p值或F值类似的统计量,它返回“每个特征与目标之间的互信息量的估计”,这个估计量在[0,1]之间取值,为0则表示两个变量独立,为1则表示两个变量完全相关。

关于F检验和互信息,可以参见官方例子:Comparison of F-test and mutual information[1]

提取简化后的特征

# 调用transform()或直接使用fit_transform方法,
# 对相同的数据集进行预处理和转换。
new_features = test.transform(X)
# 打印出特征提取前后特征数
print('原始特征数:', X.shape[1])
print('简化的特征数:', new_features.shape[1])
原始特征数: 7
简化的特征数: 3
chi_sq = pd.DataFrame(fit.scores_, columns = ["Chi_Square"], index=features.columns)
chi_sq = chi_sq.reset_index()
chi_sq.sort_values('Chi_Square',ascending=0)

皮尔逊相关系数

Pearsonr函数的接口几乎与scikit-learn单变量转换器接口一致,该函数接收两个数组 (当前例子中为x和y)作为参数,返回两个数组:每个特征的皮尔逊相关系数和p值,直接把它传入到SelectKBest函数中。

SciPy的pearsonr函数参数为两个数组,但要注意的是第一个参数x为一维数组。我们来实现一个包装器函数,这样就能像前面那样处理多维数组。

from scipy.stats import pearsonr

def multivariate_pearsonr(X, Y): 
    # 创建scores和pvalues数组,遍历数据集的每一列。
    scores, pvalues = [], []
    for column in range(X.shape[1]):
    # 只计算该列的皮尔逊相关系数和p值,并将其存储到相应数组中。
        cur_score, cur_p = pearsonr(X[:,column], Y)
        scores.append(abs(cur_score))
        pvalues.append(cur_p)
#函数最后返回包含皮尔逊相关系数和p值的元组。 
    return (np.array(scores), np.array(pvalues))

该方法衡量的是变量之间的线性相关性,结果的取值区间为

[-1,1]

, -1表示完全的负相关; +1表示完全的正相关; 0表示没有线性相关。

现在,就可以像之前那样使用转换器类,根据皮尔逊相关系数对特征进行排序。

m_pearsonr = SelectKBest(score_func=multivariate_pearsonr, k=3) 
X_pearson = m_pearsonr.fit_transform(X, Y) 
print(m_pearsonr.scores_)

[9.989e-01 9.992e-01 9.994e-01 3.903e-01 
 9.078e-03 9.203e-04 2.001e-02]
pearsonr = pd.DataFrame(m_pearsonr.scores_, columns = ["pearsonr"], index=features.columns)
pearsonr = pearsonr.reset_index()
pearsonr.sort_values('pearsonr',ascending=0)

多重共线性方差膨胀系数

方差膨胀系数(variance inflation factor,VIF)是衡量多元线性回归模型中复 (多重)共线性严重程度的一种度量。它表示回归系数估计量的方差与假设自变量间不线性相关时方差相比的比值。

多重共线性是指自变量之间存在线性相关关系,即一个自变量可以是其他一个或几个自变量的线性组合。

通常以10作为判断边界。 当VIF<10,不存在多重共线性; 当10<=VIF<100,存在较强的多重共线性; 当VIF>=100, 存在严重多重共线性。

from statsmodels.stats.outliers_influence import variance_inflation_factor

def calculate_vif(features):
    vif = pd.DataFrame()
    vif["index"] = features.columns
    vif["VIF"] = [variance_inflation_factor(features.values, i) for i in range(features.shape[1])]    
    return(vif)
  
vif = calculate_vif(features)
while vif['VIF'][vif['VIF'] > 10].any():
    remove = vif.sort_values('VIF',ascending=0)['index'][:1]
    features.drop(remove,axis=1,inplace=True)
    vif = calculate_vif(features)
    
vif

过滤法总结

最后用一张表格将过滤法做个总结,方便大家查阅学习。

说明

超参数的选择

VarianceThreshold

方差过滤,可输入方差阈值,返回方差大于阈值的新特征矩阵

看具体数据究竟是含有更多噪声还是更多有效特征一般就使用0或1来筛选也可以画学习曲线或取中位数跑模型来帮助确认

SelectKBest

用来选取K个统计量结果最佳的特征,生成看配合使用的统计量符合统计量要求的新特征矩阵

看配合使用的统计量

chi2

卡方检验,专用于分类算法,捕捉相关性

追求p小于显著性水平的特征

f_classif

F检验分类,只能捕捉线性相关性 要求数据服从正态分布

追求p小于显著性水平的特征

f_regression

F检验回归,只能捕捉线性相关性 要求数据服从正态分布

追求p小于显著性水平的特征

mutual_info_classif

互信息分类,可以捕捉任何相关性 追求互信息估计大于0的特征不能用于稀疏矩阵

追求互信息估计大于0的特征

mutual_info_regression

互信息回归,可以捕捉任何相关性 不能用于稀疏矩阵

追求互信息估计大于0的特征

pearsonr

皮尔逊相关系数,只能捕捉线性相关关系

追求p小于显著性水平的特征

左右滑动查看更多

参考资料

[1]

Comparison of F-test and mutual information: https://scikit-learn.org/stable/auto_examples/feature_selection/plot_f_test_vs_mi.html

本文分享自微信公众号 - 数据STUDIO(jim_learning),作者:云朵君

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-07-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 特征选择与特征提取最全总结

    在上篇特征选择与提取最全总结之过滤法中已经介绍了特征选择的其中一大方法--过滤法。本篇将继续介绍特征选择与特征提取方法,其主要内容如下所示。

    数据STUDIO
  • 特征选择:8 种常见的特征过滤法

    特征抽取是数据挖掘任务最为重要的一个环节,一般而言,它对最终结果的影响要高过数据挖掘算法本身。

    Python数据科学
  • 特征选择算法在微博应用中的演进历程

    用户1737318
  • 深度判别和共享特征学习的图像分类

    秋雨思童年,落花念爱霖!一场秋雨的洗礼,让我们进入了真正能感觉得到的秋季。秋季是丰收的季节,不知朋友您收获如何?但是我相信您一定硕果累累,满载着各种成果、业绩和...

    计算机视觉研究院
  • 深度判别和共享特征学习的图像分类

    秋雨思童年,落花念爱霖!一场秋雨的洗礼,让我们进入了真正能感觉得到的秋季。秋季是丰收的季节,不知朋友您收获如何?但是我相信您一定硕果累累,满载着各种成果、业绩和...

    计算机视觉研究院
  • 《机器学习》笔记-特征选择与稀疏学习(11)

    如今机器学习和深度学习如此火热,相信很多像我一样的普通程序猿或者还在大学校园中的同学,一定也想参与其中。不管是出于好奇,还是自身充电,跟上潮流,我觉得都值得试一...

    机器学习算法工程师
  • TensorFlow系列专题(二):机器学习基础

    数据预处理的方式较多,针对不同类型的数据,预处理的方式和内容也不尽相同,这里我们简单介绍几种较为常用的方式:

    磐创AI
  • 特征选择

    过滤式是过滤式的方法先对数据集进行特征选择,然后再训练学习器,特征选择过程与后续学习器无关,也就是说我们先用特征选择过程对初始特征进行“过滤”,再用过滤后的特征...

    数据山谷
  • 【机器学习】快速入门特征工程

    这个结果并不是想要看到的,所以加上参数,得到想要的结果,在这里把这个处理数据的技巧用专业的称呼"one-hot"编码。

    后端码匠
  • 卷积神经网络(CNN)原理

    对于之前介绍的卷积运算过程,我们用一张动图来表示更好理解些。一下计算中,假设图片长宽相等,设为N

    Lanson
  • 《机器学习》-- 第十一章 特征选择与稀疏学习

    在机器学习中特征选择是一个重要的“数据预处理”(data preprocessing)过程,即试图从数据集的所有特征中挑选出与当前学习任务相关的特征子集,再利用...

    fireWang
  • 特征工程

    特征工程和数据清洗转换是比赛中至关重要的一块,因为数据和特征决定了机器学习的上限,而算法和模型只是逼近这个上限而已,所以特征工程的好坏往往决定着最后的结果

    mathor
  • 天池-半导体质量预测

    1) 提取特征后,xgboost的mse为0.0325341683406 2) 单个随机森林的5折交叉验证的平均mse为0.0288353227614 (max...

    DuncanZhou
  • 特征工程系列:特征筛选的原理与实现(上)

    本篇是来自木东居士的超赞文章,是关于特征工程的一些常用的方法理论以及python实现,大家在做特征工程的时候,可以有所借鉴。

    Sam Gor
  • 特征工程系列:特征筛选的原理与实现(上)

    数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。由此可见,特征工程在机器学习中占有相当重要的地位。在实际应用当中,可以说特征工程是机器学习成功...

    石晓文
  • 特征工程系列:特征筛选的原理与实现(上)

    数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。由此可见,特征工程在机器学习中占有相当重要的地位。在实际应用当中,可以说特征工程是机器学习成功...

    Datawhale
  • 特征工程系列:特征筛选的原理与实现(上)

    数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。由此可见,特征工程在机器学习中占有相当重要的地位。在实际应用当中,可以说特征工程是机器学习成功...

    木东居士
  • 单细胞RNA-seq预处理工具比较分析(bioRxiv)

    NGS系列文章包括NGS基础、转录组分析 (Nature重磅综述|关于RNA-seq你想知道的全在这)、ChIP-seq分析 (ChIP-seq基本分析流程)、...

    生信宝典
  • BCI-EEG脑电数据处理

    EEG信号特征提取就是以脑电信号作为源信号,确定各种参数并以此为向量组成表征信号特征的特征向量。

    MiChong

扫码关注云+社区

领取腾讯云代金券