写点什么

数据预处理和特征工程 - 数据预处理 - 特征选择 - 方差过滤

  • 2022-11-12
    山东
  • 本文字数:3165 字

    阅读完需:约 10 分钟


这里只说特征选择


我们有四种方法可以用来选择特征:过滤法,嵌入法,包装法,和降维算法。


import pandas as pddata = pd.read_csv(r"D:\ObsidianWorkSpace\SklearnData\digit recognizor.csv")data.shape---(42000, 785)
data.iloc[:5,[0,1,784]]---label pixel0 pixel7830 1 0 01 0 0 02 1 0 03 4 0 04 0 0 0
X = data.iloc[:,1:]y = data.iloc[:,0]X.shape---(42000, 784)
复制代码

Filter 过滤法

过滤方法通常用作预处理步骤,特征选择完全独立于任何机器学习算法。


方差过滤

VarianceThreshold(threshold=0.0)# threshold:阈值,方差小于该值的特征将被删除,默认为0
复制代码


一个特征本身的方差很小,就表示样本在这个特征上基本没有差异,甚至整个特征的取值都相同(方差为 0),那这个特征对于样本区分没有什么作用。所以无论接下来的特征工程要做什么,都要优先消除方差为 0 的特征


from sklearn.feature_selection import VarianceThresholdselector = VarianceThreshold()# 实例化,不填参数默认方差为0X_var0 = selector.fit_transform(X)# 获取删除不合格的特征之后的新特征矩阵X_var0.shape---(42000, 708)
复制代码


果要删除固定数量的特征或者指定方差阈值,可以用以下方法,这里先演示删除一半特征


import numpy as npX_fsvar = VarianceThreshold(np.median(X.var().values)).fit_transform(X)X_fsvar.shape---(42000, 392)
X.var().head()# 每一列的方差---pixel0 0.0pixel1 0.0pixel2 0.0pixel3 0.0pixel4 0.0dtype: float64
复制代码


如果我们要保留 100 个特征,那么先用 X.var()获取所有特征的方差,然后排序,取第 100 个值作为阈值即可。其他数量同理


当特征是二分类时,特征的取值就是伯努利随机变量,根据之前的知识,变量的方差为



这里假设 p=0.8,也就是我们自己取 p=0.8,即二分类特征中某种分类占到 80%以上的时候删除特征


X_bvar = VarianceThreshold(0.8 * (1-0.8)).fit_transform(X)# 这里求得Var(X),注意是大XX_bvar.shape---(42000, 685)
复制代码

方差过滤对模型的影响

这里我们展示对 KNN 和对随机森林的影响


from sklearn.ensemble import RandomForestClassifier as RFC from sklearn.neighbors import KNeighborsClassifier as KNN from sklearn.model_selection import cross_val_scoreimport numpy as np
X = data.iloc[:,1:]y = data.iloc[:,0]X_fsvar = VarianceThreshold(np.median(X.var().values)).fit_transform(X) # 这里用删除一半作为阈值
复制代码


KNN 方差过滤前


cross_val_score(KNN(),X,y,cv=5).mean()# 运行时间超过半小时---0.9658569700264943
%%timeitcross_val_score(KNN(),X,y,cv=5).mean()# 运行时间超过4小时---33min 58s ± 43.9 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
复制代码


KNN 方差过滤后


cross_val_score(KNN(),X_fsvar,y,cv=5).mean()# 运行时间超过20分钟---0.9659997478150573
%%timeitcross_val_score(KNN(),X,y,cv=5).mean()# 运行时间超过两小时---20min ± 4min 55 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
复制代码


可以看出,对于 KNN,过滤后的效果十分明显:准确率稍有提升,平均运行时间减少了 10 分钟,特征选择过后算法的效率上升了 1/3。


随机森林方差过滤前


cross_val_score(RFC(n_estimators=10,random_state=0),X,y,cv=5).mean()---0.9380003861799541
%%timeitcross_val_score(RFC(n_estimators=10,random_state=0),X,y,cv=5).mean()---11.5 s ± 305 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
复制代码


随机森林方差过滤后


cross_val_score(RFC(n_estimators=10,random_state=0),X_fsvar,y,cv=5).mean()---0.9388098166696807
%%timeitcross_val_score(RFC(n_estimators=10,random_state=0),X,y,cv=5).mean()---11.1 s ± 72 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
复制代码


可以观察到的是,随机森林的准确率略逊于 KNN,但运行时间却连 KNN 的 1%都不到,只需要十几秒钟。其次,方差过滤后,随机森林的准确率也微弱上升,但运行时间却几乎是没什么变化,依然是 11 秒钟。


为什么随机森林运行如此之快?为什么方差过滤对随机森林没很大的有影响?这是由于两种算法的原理中涉及到的计算量不同。最近邻算法 KNN,传统的单棵决策树,支持向量机 SVM,神经网络,回归算法,都需要遍历特征或升维来进行运算,所以他们本身的运算量就很大,需要的时间就很长,因此方差过滤这样的特征选择对他们来说就尤为重要。但对于不需要遍历特征的算法,比如随机森林,它随机选取特征进行分枝,本身运算就非常快速,因此特征选择对它来说效果一般


这其实很容易理解,无论过滤法如何降低特征的数量,随机森林也只会选取固定数量的特征来建模;而最近邻算法就不同了,特征越少,距离计算的维度就越少,模型明显会随着特征的减少变得轻量。


因此,过滤法的主要对象是:需要遍历特征或升维的算法们。过滤法的主要目的是:在维持算法表现的前提下,帮助算法们降低计算成本。


过滤法对随机森林效果不明显,却对树模型明显从算法原理上来说,传统决策树需要遍历所有特征,计算不纯度后进行分枝,而随机森林却是随机选择特征进行计算和分枝,因此随机森林的运算更快,过滤法对随机森林无用,对决策树却有用但这里我们讨论的是 sklearn 中的决策树。在 sklearn 中,决策树和随机森林都是随机选择特征进行分枝,但决策树在建模过程中随机抽取的特征数目却远远超过随机森林当中每棵树随机抽取的特征数目。比如说对于这个 780 维的数据,随机森林每棵树只会抽取 1020 个特征,而决策树可能会抽取 300400 个特征

可以这么理解,随机森林是构建多棵决策树然后投票得到最终结果,所以不需要要求每棵树精确度太高,所以选取少量特征分枝即可。但是,对于决策树,只有一棵,因此需要尽量精确的构建模型,虽然是选取特征,更精确的决策树也就要求更多的特征。这也体现了集成算法的优势

因此,过滤法对随机森林无用,却对决策树有用。并且,在 sklearn 中,随机森林中的每棵树都比单独的一棵决策树简单得多,高维数据下的随机森林的计算比决策树快很多。


实际上我们继续提高随机森林的 n_estimators,其 score 会继续上升,这里仅做尝试,不画学习曲线了


score = cross_val_score(RandomForestClassifier(n_estimators=50),X,y,cv=3).mean()score---0.9611430007334194
score = cross_val_score(RandomForestClassifier(n_estimators=100),X,y,cv=3).mean()score---0.9621193895614663
复制代码


对受影响的算法来说(KNN、DT、SVM),我们可以将方差过滤的影响总结如下



在我们的对比当中,我们使用的方差阈值是特征方差的中位数,因此属于阈值比较大,过滤掉的特征比较多的情况。我们可以观察到,无论是 KNN 还是随机森林,在过滤掉一半特征之后,模型的精确度都上升了。这说明被我们过滤掉的特征在当前随机模式(random_state = 0)下大部分是噪音。那我们就可以保留这个去掉了一半特征的数据,来为之后的特征选择做准备。如果过滤之后模型的效果反而变差了,我们就可以认为,被我们过滤掉的特征中有很多都有有效特征,那我们就放弃过滤,使用其他手段来进行特征选择。

选取超参数 threshold

每个数据集不一样,只能自己去尝试。这里的方差阈值,其实相当于是一个超参数,要选定最优的超参数,我们可以画学习曲线,找模型效果最好的点。但现实中,我们往往不会这样去做,因为这样会耗费大量的时间。我们只会使用阈值为 0 或者阈值很小的方差过滤,来为我们优先消除一些明显用不到的特征,然后我们会选择更优的特征选择方法继续削减特征数量。


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


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

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

还未添加个人简介

评论

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