数据挖掘:特征工程——特征提取与选择( 七 )


主要思想是反复的构建模型(如SVM或者回归模型)然后选出最好的(或者最差的)的特征(可以根据系数来选),把选出来的特征放到一遍,然后在剩余的特征上重复这个过程,直到所有特征都遍历了 。这个过程中特征被消除的次序就是特征的排序 。因此,这是一种寻找最优特征子集的贪心算法 。
RFE的稳定性很大程度上取决于在迭代的时候底层用哪种模型 。例如,假如RFE采用的普通的回归,没有经过正则化的回归是不稳定的,那么RFE就是不稳定的;假如采用的是Ridge,而用Ridge正则化的回归是稳定的,那么RFE就是稳定的 。
提供了 RFE 包,可以用于特征消除,还提供了 RFECV,可以通过交叉验证来对的特征进行排序,以此来选择最佳数量的特征:对于一个数量为d的的集合,他的所有的子集的个数是2的d次方减1(包含空集) 。指定一个外部的学习算法,比如SVM之类的 。通过该算法计算所有子集的 error 。选择error最小的那个子集作为所挑选的特征 。
官方解释:对特征含有权重的预测模型(例如,线性模型对应参数),RFE通过递归减少考察的特征集规模来选择特征 。首先,预测模型在原始特征上训练,每个特征指定一个权重 。之后,那些拥有最小绝对值权重的特征被踢出特征集 。如此往复递归,直至剩余的特征数量达到所需的特征数量 。
from sklearn.feature_selection import RFEfrom sklearn.linear_model import LinearRegressionfrom sklearn.datasets import load_bostonboston = load_boston()X = boston["data"]Y = boston["target"]names = boston["feature_names"]#use linear regression as the modellr = LinearRegression()#rank all features, i.e continue the elimination until the last onerfe = RFE(lr, n_features_to_select=1)rfe.fit(X,Y)print("Features sorted by their rank:")print(sorted(zip(rfe.ranking_, names)))Features sorted by their rank:[(1, 'NOX'), (2, 'RM'), (3, 'CHAS'), (4, 'PTRATIO'), (5, 'DIS'), (6, 'LSTAT'), (7, 'RAD'), (8, 'CRIM'), (9, 'INDUS'), (10, 'ZN'), (11, 'TAX'), (12, 'B'), (13, 'AGE')]
5.3 嵌入法
在过滤式和包裹式特征选择方法中,特征选择过程与学习器训练过程有明显的分别 。单变量特征选择方法独立的衡量每个特征与响应变量之间的关系 。而有些机器学习方法本身就具有对特征进行打分的机制,或者很容易将其运用到特征选择任务中 。
嵌入式特征选择是将特征选择与学习器训练过程融为一体,两者在同一个优化过程中完成的 。即学习器训练过程中自动进行了特征选择 。
常用的方法包括:
利用正则化,如L_1, L_2 范数,主要应用于如线性回归、逻辑回归以及支持向量机(SVM)等算法 。使用决策树思想,包括决策树、随机森林、等 。5.3.1 线性模型和正则化 5.3.1.1 线性模型
使用L1范数作为惩罚项的线性模型( )除了降低过拟合风险之外,还有一个好处,它更容易获得稀疏解:大部分特征对应的系数为0 。当你希望减少特征的维度以用于其它分类器时,可以通过 . 来选择不为0的系数 。特别指出,常用于此目的的稀疏预测模型有 .Lasso(回归),. 和 svm.(分类):
下面将介绍如何用回归模型的系数来选择特征 。越是重要的特征在模型中对应的系数就会越大,而跟输出变量越是无关的特征对应的系数就会越接近于0 。在噪音不多的数据上,或者是数据量远远大于特征数的数据上,如果特征之间相对来说是比较独立的,那么即便是运用最简单的线性回归模型也一样能取得非常好的效果 。
from sklearn.linear_model import LinearRegressionimport numpy as np# A helper method for pretty-printing linear modelsdef pretty_print_linear(coefs, names=None, sort=False):if names == None:names = ["X%s" % x for x in range(len(coefs))]lst = zip(coefs, names)if sort:lst = sorted(lst, key=lambda x: -np.abs(x[0]))return " + ".join("%s * %s" % (round(coef, 3), name) for coef, name in lst)np.random.seed(0)# 有了这段代码,下次再生成随机数的时候,与上次一样的结果size = 5000# 表示抽取多少个样本# 随机生成3个特征的样本,每个维度的特征都是服从期望为0,标准差为1的正态分布X = np.random.normal(0, 1, (size, 3))# 抽取5000个样本,每个样本都是3维的# Y = X0 + 2*X1 + noiseY = X[:, 0] + 2 * X[:, 1] + np.random.normal(0, 2, size)lr = LinearRegression()lr.fit(X, Y)print("Linear model:", pretty_print_linear(lr.coef_))>>> Linear model: 0.984 * X0 + 1.995 * X1 + -0.041 * X2