lasso特征选择python_转:结合Scikit-learn介绍几种常用的特征选择方法-2

4.2 平均精确率减少 Mean decrease accuracy

另一种常用的特征选择方法就是直接度量每个特征对模型精确率的影响。主要思路是打乱每个特征的特征值顺序,并且度量顺序变动对模型的精确率的影响。很明显,对于不重要的变量来说,打乱顺序对模型的精确率影响不会太大,但是对于重要的变量来说,打乱顺序就会降低模型的精确率。

这个方法sklearn中没有直接提供,但是很容易实现,下面继续在波士顿房价数据集上进行实现。

fromsklearn.cross_validationimportShuffleSplit

fromsklearn.metricsimportr2_score

fromcollectionsimportdefaultdict

X = boston["data"]

Y = boston["target"]

rf = RandomForestRegressor()

scores = defaultdict(list)

#crossvalidate the scores on a number of different random splits of the data

fortrain_idx, test_idxinShuffleSplit(len(X),100, .3):

X_train, X_test = X[train_idx], X[test_idx]

Y_train, Y_test = Y[train_idx], Y[test_idx]

r = rf.fit(X_train, Y_train)

acc = r2_score(Y_test, rf.predict(X_test))

foriinrange(X.shape[1]):

X_t = X_test.copy()

np.random.shuffle(X_t[:, i])

shuff_acc = r2_score(Y_test, rf.predict(X_t))

scores[names[i]].append((acc-shuff_acc)/acc)

print("Features sorted by their score:")

print(sorted([(round(np.mean(score),4), feat)for

feat, score inscores.items()], reverse=True))

Features sorted by their score: [(0.7276, ‘LSTAT’), (0.5675, ‘RM’),

(0.0867, ‘DIS’), (0.0407, ‘NOX’), (0.0351, ‘CRIM’), (0.0233,

‘PTRATIO’), (0.0168, ‘TAX’), (0.0122, ‘AGE’), (0.005, ‘B’),

(0.0048, ‘INDUS’), (0.0043, ‘RAD’), (0.0004, ‘ZN’), (0.0001,

‘CHAS’)]

在这个例子当中,LSTAT和RM这两个特征对模型的性能有着很大的影响,打乱这两个特征的特征值使得模型的性能下降了73%和57%。注意,尽管这些我们是在所有特征上进行了训练得到了模型,然后才得到了每个特征的重要性测试,这并不意味着我们扔掉某个或者某些重要特征后模型的性能就一定会下降很多,因为即便某个特征删掉之后,其关联特征一样可以发挥作用,让模型性能基本上不变。

5 两种顶层特征选择算法

之所以叫做顶层,是因为他们都是建立在基于模型的特征选择方法基础之上的,例如回归和SVM,在不同的子集上建立模型,然后汇总最终确定特征得分。

5.1 稳定性选择 Stability selection

稳定性选择是一种基于二次抽样和选择算法相结合较新的方法,选择算法可以是回归、SVM或其他类似的方法。它的主要思想是在不同的数据子集和特征子集上运行特征选择算法,不断的重复,最终汇总特征选择结果,比如可以统计某个特征被认为是重要特征的频率(被选为重要特征的次数除以它所在的子集被测试的次数)。理想情况下,重要特征的得分会接近100%。稍微弱一点的特征得分会是非0的数,而最无用的特征得分将会接近于0。

sklearn在随机lasso和随机逻辑回归中有对稳定性选择的实现。

fromsklearn.linear_modelimportRandomizedLasso

fromsklearn.datasetsimportload_boston

boston = load_boston()

#using the Boston housing data.

#Data gets scaled automatically by sklearn's implementation

X = boston["data"]

Y = boston["target"]

names = boston["feature_names"]

rlasso = RandomizedLasso(alpha=0.025)

rlasso.fit(X, Y)

print("Features sorted by their score:")

print(sorted(zip(map(lambdax: round(x,4), rlasso.scores_),

names), reverse=True))

Features sorted by their score: [(1.0, ‘RM’), (1.0, ‘PTRATIO’),

(1.0, ‘LSTAT’), (0.62, ‘CHAS’), (0.595, ‘B’), (0.39, ‘TAX’),

(0.385, ‘CRIM’), (0.25, ‘DIS’), (0.22, ‘NOX’), (0.125, ‘INDUS’),

(0.045, ‘ZN’), (0.02, ‘RAD’), (0.015, ‘AGE’)]

在上边这个例子当中,最高的3个特征得分是1.0,这表示他们总会被选作有用的特征(当然,得分会收到正则化参数alpha的影响,但是sklearn的随机lasso能够自动选择最优的alpha)。接下来的几个特征得分就开始下降,但是下降的不是特别急剧,这跟纯lasso的方法和随机森林的结果不一样。能够看出稳定性选择对于克服过拟合和对数据理解来说都是有帮助的:总的来说,好的特征不会因为有相似的特征、关联特征而得分为0,这跟Lasso是不同的。对于特征选择任务,在许多数据集和环境下,稳定性选择往往是性能最好的方法之一。

5.2 递归特征消除 Recursive feature elimination (RFE)

递归特征消除的主要思想是反复的构建模型(如SVM或者回归模型)然后选出最好的(或者最差的)的特征(可以根据系数来选),把选出来的特征放到一遍,然后在剩余的特征上重复这个过程,直到所有特征都遍历了。这个过程中特征被消除的次序就是特征的排序。因此,这是一种寻找最优特征子集的贪心算法。

RFE的稳定性很大程度上取决于在迭代的时候底层用哪种模型。例如,假如RFE采用的普通的回归,没有经过正则化的回归是不稳定的,那么RFE就是不稳定的;假如采用的是Ridge,而用Ridge正则化的回归是稳定的,那么RFE就是稳定的。

Sklearn提供了RFE包,可以用于特征消除,还提供了RFECV,可以通过交叉验证来对的特征进行排序。

fromsklearn.feature_selectionimportRFE

fromsklearn.linear_modelimportLinearRegression

boston = load_boston()

X = boston["data"]

Y = boston["target"]

names = boston["feature_names"]

#use linear regression as the model

lr = LinearRegression()

#rank all features, i.e continue the elimination until the last one

rfe = RFE(lr, n_features_to_select=1)

rfe.fit(X,Y)

print("Features sorted by their rank:")

print(sorted(zip(map(lambdax: round(x,4), rfe.ranking_), names)))

Features sorted by their rank: [(1.0, ‘NOX’), (2.0, ‘RM’), (3.0,

‘CHAS’), (4.0, ‘PTRATIO’), (5.0, ‘DIS’), (6.0, ‘LSTAT’), (7.0,

‘RAD’), (8.0, ‘CRIM’), (9.0, ‘INDUS’), (10.0, ‘ZN’), (11.0, ‘TAX’),

(12.0, ‘B’), (13.0, ‘AGE’)]

6 一个完整的例子

下面将本文所有提到的方法进行实验对比,数据集采用Friedman #1 回归数据(这篇论文中的数据)。数据是用这个公式产生的:

a4c26d1e5885305701be709a3d33442f.png

X1到X5是由单变量分布生成的,e是标准正态变量N(0,1)。另外,原始的数据集中含有5个噪音变量

X5,…,X10,跟响应变量是独立的。我们增加了4个额外的变量X11,…X14,分别是X1,…,X4的关联变量,通过f(x)=x+N(0,0.01)生成,这将产生大于0.999的关联系数。这样生成的数据能够体现出不同的特征排序方法应对关联特征时的表现。

接下来将会在上述数据上运行所有的特征选择方法,并且将每种方法给出的得分进行归一化,让取值都落在0-1之间。对于RFE来说,由于它给出的是顺序而不是得分,我们将最好的5个的得分定为1,其他的特征的得分均匀的分布在0-1之间。

fromsklearn.datasetsimportload_boston

fromsklearn.linear_modelimport(LinearRegression, Ridge,

Lasso, RandomizedLasso)

fromsklearn.feature_selectionimportRFE, f_regression

fromsklearn.preprocessingimportMinMaxScaler

fromsklearn.ensembleimportRandomForestRegressor

importnumpy as np

fromminepyimportMINE

np.random.seed(0)

size = 750

X = np.random.uniform(0,1, (size,14))

#"Friedamn #1” regression problem

Y = (10* np.sin(np.pi*X[:,0]*X[:,1]) +20*(X[:,2] - .5)**2+

10*X[:,3] +5*X[:,4] + np.random.normal(0,1))

#Add 3 additional correlated variables (correlated with X1-X3)

X[:,10:] = X[:,:4] + np.random.normal(0, .025, (size,4))

names = ["x%s"% iforiinrange(1,15)]

ranks = {}

defrank_to_dict(ranks, names, order=1):

minmax = MinMaxScaler()

ranks = minmax.fit_transform(order*np.array([ranks]).T).T[0]

ranks = map(lambdax: round(x,2), ranks)

returndict(zip(names, ranks ))

lr = LinearRegression(normalize=True)

lr.fit(X, Y)

ranks["Linear reg"] = rank_to_dict(np.abs(lr.coef_), names)

ridge = Ridge(alpha=7)

ridge.fit(X, Y)

ranks["Ridge"] = rank_to_dict(np.abs(ridge.coef_), names)

lasso = Lasso(alpha=.05)

lasso.fit(X, Y)

ranks["Lasso"] = rank_to_dict(np.abs(lasso.coef_), names)

rlasso = RandomizedLasso(alpha=0.04)

rlasso.fit(X, Y)

ranks["Stability"] = rank_to_dict(np.abs(rlasso.scores_), names)

#stop the search when 5 features are left (they will get equal scores)

rfe = RFE(lr, n_features_to_select=5)

rfe.fit(X,Y)

ranks["RFE"] = rank_to_dict(map(float, rfe.ranking_), names, order=-1)

rf = RandomForestRegressor()

rf.fit(X,Y)

ranks["RF"] = rank_to_dict(rf.feature_importances_, names)

f, pval = f_regression(X, Y, center=True)

ranks["Corr."] = rank_to_dict(f, names)

mine = MINE()

mic_scores = []

foriinrange(X.shape[1]):

mine.compute_score(X[:,i], Y)

m = mine.mic()

mic_scores.append(m)

ranks["MIC"] = rank_to_dict(mic_scores, names)

r = {}

fornameinnames:

r[name] = round(np.mean([ranks[method][name]

formethodinranks.keys()]),2)

methods = sorted(ranks.keys())

ranks["Mean"] = r

methods.append("Mean")

print("\t%s"%"\t".join(methods))

fornameinnames:

print("%s\t%s"% (name,"\t".join(map(str,

[ranks[method][name] formethodinmethods]))))

a4c26d1e5885305701be709a3d33442f.png

从以上结果中可以找到一些有趣的发现:

特征之间存在线性关联关系,每个特征都是独立评价的,因此X1,…X4的得分和X11,…X14的得分非常接近,而噪音特征X5,…,X10正如预期的那样和响应变量之间几乎没有关系。由于变量X3是二次的,因此X3和响应变量之间看不出有关系(除了MIC之外,其他方法都找不到关系)。这种方法能够衡量出特征和响应变量之间的线性关系,但若想选出优质特征来提升模型的泛化能力,这种方法就不是特别给力了,因为所有的优质特征都不可避免的会被挑出来两次。

Lasso能够挑出一些优质特征,同时让其他特征的系数趋于0。当如需要减少特征数的时候它很有用,但是对于数据理解来说不是很好用。(例如在结果表中,X11,X12,X13的得分都是0,好像他们跟输出变量之间没有很强的联系,但实际上不是这样的)

MIC对特征一视同仁,这一点上和关联系数有点像,另外,它能够找出X3和响应变量之间的非线性关系。

随机森林基于不纯度的排序结果非常鲜明,在得分最高的几个特征之后的特征,得分急剧的下降。从表中可以看到,得分第三的特征比第一的小4倍。而其他的特征选择算法就没有下降的这么剧烈。

Ridge将回归系数均匀的分摊到各个关联变量上,从表中可以看出,X11,…,X14和X1,…,X4的得分非常接近。

稳定性选择常常是一种既能够有助于理解数据又能够挑出优质特征的这种选择,在结果表中就能很好的看出。像Lasso一样,它能找到那些性能比较好的特征(X1,X2,X4,X5),同时,与这些特征关联度很强的变量也得到了较高的得分。

总结

对于理解数据、数据的结构、特点来说,单变量特征选择是个非常好的选择。尽管可以用它对特征进行排序来优化模型,但由于它不能发现冗余(例如假如一个特征子集,其中的特征之间具有很强的关联,那么从中选择最优的特征时就很难考虑到冗余的问题)。

正则化的线性模型对于特征理解和特征选择来说是非常强大的工具。L1正则化能够生成稀疏的模型,对于选择特征子集来说非常有用;相比起L1正则化,L2正则化的表现更加稳定,由于有用的特征往往对应系数非零,因此L2正则化对于数据的理解来说很合适。由于响应变量和特征之间往往是非线性关系,可以采用basis

expansion的方式将特征转换到一个更加合适的空间当中,在此基础上再考虑运用简单的线性模型。

随机森林是一种非常流行的特征选择方法,它易于使用,一般不需要feature

engineering、调参等繁琐的步骤,并且很多工具包都提供了平均不纯度下降方法。它的两个主要问题,1是重要的特征有可能得分很低(关联特征问题),2是这种方法对特征变量类别多的特征越有利(偏向问题)。尽管如此,这种方法仍然非常值得在你的应用中试一试。

特征选择在很多机器学习和数据挖掘场景中都是非常有用的。在使用的时候要弄清楚自己的目标是什么,然后找到哪种方法适用于自己的任务。当选择最优特征以提升模型性能的时候,可以采用交叉验证的方法来验证某种方法是否比其他方法要好。当用特征选择的方法来理解数据的时候要留心,特征选择模型的稳定性非常重要,稳定性差的模型很容易就会导致错误的结论。对数据进行二次采样然后在子集上运行特征选择算法能够有所帮助,如果在各个子集上的结果是一致的,那就可以说在这个数据集上得出来的结论是可信的,可以用这种特征选择模型的结果来理解数据。

Tips

什么是卡方检验?用方差来衡量某个观测频率和理论频率之间差异性的方法

什么是皮尔森卡方检验?这是一种最常用的卡方检验方法,它有两个用途:1是计算某个变量对某种分布的拟合程度,2是根据两个观测变量的Contingency

table来计算这两个变量是否是独立的。主要有三个步骤:第一步用方差和的方式来计算观测频率和理论频率之间卡方值;第二步算出卡方检验的自由度(行数-1乘以列数-1);第三步比较卡方值和对应自由度的卡方分布,判断显著性。

什么是p-value?简单地说,p-value就是为了验证假设和实际之间一致性的统计学意义的值,即假设检验。有些地方叫右尾概率,根据卡方值和自由度可以算出一个固定的p-value,

什么是响应变量(response

value)?简单地说,模型的输入叫做explanatroy variables,模型的输出叫做response

variables,其实就是要验证该特征对结果造成了什么样的影响

什么是零假设(null

hypothesis)?在相关性检验中,一般会取“两者之间无关联”作为零假设,而在独立性检验中,一般会取“两者之间是独立”作为零假设。与零假设相对的是备择假设(对立假设),即希望证明是正确的另一种可能。

That’s it

References

http://blog.datadive.net/selecting-good-features-part-i-univariate-selection/

http://blog.datadive.net/selecting-good-features-part-ii-linear-models-and-regularization/

http://scikit-learn.org/stable/modules/feature_selection.html#univariate-feature-selection

http://www.quora.com/What-are-some-feature-selection-methods

http://www.quora.com/What-are-some-feature-selection-algorithms

http://www.quora.com/What-are-some-feature-selection-methods-for-SVMs

http://www.quora.com/What-is-the-difference-between-principal-component-analysis-PCA-and-feature-selection-in-machine-learning-Is-PCA-a-means-of-feature-selection

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/291315.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

shell中条件判断if中的-z到-d的意思

shell中条件判断if中的-z到-d的意思 [ -a FILE ] 如果 FILE 存在则为真。 [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。 [ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真。 [ -d FILE ] 如果 FILE 存在且是一个目录则为真。 [ -e FILE ] 如果 FILE 存在则为真。…

Mac Generating Pods project Abort trap: 6

为什么80%的码农都做不了架构师?>>> 为项目添加cocoapods如果产生此种错误时,主要有以下几点原因: 1,cocoapods版本过低: 打开终端在终端输入:pod --version,目前最新版本是1.2.0(2017年3月),如果发现版本过低,则可以在终端输入以下命令:gem install co…

svn 服务器搭建

2019独角兽企业重金招聘Python工程师标准>>> Svn搭建 1. Linux 搭建 YUM 服务器 [rootlocalhost conf]# yum install -y subversion 2.验证安装版本: [rootlocalhost conf]# svnserve –version 3.创建SVN 版本库 [rootlocalhost conf]# mkdir /v…

Android之提示can‘t execute: Permission denied解决办法

1、问题 在手机里面执行文件的时候提示 cant execute: Permission denied 一开始以为是没有root权限,自己傻逼了,错误意思是,不能执行,权限定义, 2、解决办法 chmod 777 file 给文件可执行就可以。 一般把文件放到…

C# 使用 ValueTasks

C# 7 带有更灵活的 await 关键字;它现在可以等待任何提供 GetAwaiter 方法的对象。一种可用于等待的新类型是 ValueTask。与 Task 类相反,ValueTask 是一个结构。这具有性能优势,因为 ValueTask 在堆上没有对象。与异步方法调用相比&#xff…

LeetCode之Reverse String II

1、题目 Given a string and an integer k, you need to reverse the first k characters for every 2k characters counting from the start of the string. If there are less than k characters left, reverse all of them. If there are less than 2k but greater than or …

Electron - 创建跨平台的桌面客户的应用程序

Electron 框架的前身是 Atom Shell,可以让你写使用 JavaScript,HTML 和 CSS 构建跨平台的桌面应用程序。它是基于io.js 和 Chromium 开源项目,并用于在 Atom 编辑器中。Electron 是开源的,由 GitHub 维护,有一个活跃的…

Cognos TM1_10.1.1服务端配置

场景:本文继Cognos TM1_10.1.1服务端安装 之后,简单的说一下本人对简单配置的拙见,确保服务端在安装过程一切正常,成功安装。 1:进入TM的Cognos Configuration 2:如下图,选中环境,这里可以看出…

java黄油刀_一篇文章玩转ButterKnife,让代码更简洁

前言话说,Android开发的兄弟们都知道,每次初始化控件,设置相应的事件,写的那点过程多而且恶心。我们先一块回顾下不堪的曾经~那些年,我们是这样初始化控件:// 每次的习惯上来写一个initView()方法tvContent…

图片加载框架Picasso - 源码分析

简书:图片加载框架Picasso - 源码分析 前一篇文章讲了Picasso的详细用法,Picasso 是一个强大的图片加载缓存框架,一个非常优秀的开源库,学习一个优秀的开源库,,我们不仅仅是学习它的用法,停留在…

Bit Manipulation —— 位运算

1、介绍 Bit Manipulation(位运算): 一共五种运算:与,或,异或,左移,右移。2、算法题目一般使用总结: (1)n & (n-1)能够消灭n中最右侧的一个1。…

jQuery 表单选择器

jQuery 代码&#xff1a; <script type"text/javaScript"> $(document).ready(function(){ $("#form1 input:enabled").val("这里变化了");//改变表单内可用<input> 元素 $("#form1 input:disabled").val("这里也变了…

nodejs的内存管理,垃圾回收机制

2019独角兽企业重金招聘Python工程师标准>>> 要点记录&#xff1a; 1、网页js、命令行工具&#xff0c;快进快出的&#xff0c;即时内存泄露&#xff0c;无内存管理必要! 2、服务器端nodejs和其他正规语言一样存在内存泄露。 3、nodejs基于谷歌v8js引擎&#xff…

java实体中文字段_java - Spring JPA实体类是否可以包含不在数据库表中的非数据库字段 - SO中文参考 - www.soinside.com...

我在SpringBoot中使用Spring JPA和Spring Data Rest。我有一个称为用户的数据库表和该表的实体。我没有此应用程序的控制器。EntityTable(name "USER")public class User implements Serializable {IdGeneratedValue(strategy GenerationType.IDENTITY)Basic(optio…

Redis【第二篇】集群搭建

第一步&#xff1a;准备 1.安装包 ruby-2.4.0.tar.gz rubygems-2.6.10.tgz zlib-1.2.11.tar.gz redis-3.3.2.gem 2. 架构&#xff1a; 名称IP端口节点属性redisA192.168.6.1286379主节点redisB192.168.6.1289379从节点redisC192.168.6.1296379主节点redisD192.168.6.1299379从节…

LeetCode之Ransom Note

1、题目 Given an arbitrary ransom note string and another string containing letters from all the magazines, write a function that will return true if the ransom note can be constructed from the magazines ; otherwise, it will return false. Each letter in th…

(转)java中对集合对象list的几种循环访问总结

Java集合的Stack、Queue、Map的遍历在集合操作中&#xff0c;常常离不开对集合的遍历&#xff0c;对集合遍历一般来说一个foreach就搞定了&#xff0c;但是&#xff0c;对于Stack、Queue、Map类型的遍历&#xff0c;还是有一些讲究的。最近看了一些代码&#xff0c;在便利Map时…

NET框架下如何使用PaddleOCRSharp

打开VSIDE,新建Windows窗体应用(.NETFramework)类型的项目&#xff0c;选择一个.NET框架&#xff0c;如.NETFramework 4.0&#xff0c;右键点击项目&#xff0c;选择属性》生成&#xff0c;目标平台设置成X64.菜单》工具》选项&#xff0c;Nuget包管理器》程序包管理&#xff0…

Android在全球的市场份额跃居全球第一

Android在全球的市场份额跃居全球第一2011年第一季度&#xff0c;Android在全球的市场份额首次超过塞班系统&#xff0c;跃居全球第一。 2012年2月数据&#xff0c;Android占据全球智能手机操作系统市场52.5%的份额&#xff0c;中国市场占有率为68.4%. 有兴趣的&#xff0c;可加…

LeetCode之Add Digits

1、题目 Given a non-negative integer num, repeatedly add all its digits until the result has only one digit. For example: Given num 38, the process is like: 3 8 11, 1 1 2. Since 2 has only one digit, return it. 2、代码实现 public class Solution {publi…