Python sklearn学习之特征选择

Python sklearn学习之特征选择



一般而言,特征选择的过程是指从已有的M个特征(Feature)中选择N个特征使得系统的特定指标最优化,是从原始特征中选择出一些最有效特征以降低数据集维度的过程。其可看为是一个搜索寻优问题。

原始数据
特征子集
选中特征
开始
子集产生
子集评价
停止策略
结果验证

1. 移除低方差特征

VarianceThreshold 是特征选择的一个简单基本方法,它会移除所有那些方差不满足一些阈值的特征。默认情况下,它将会移除所有的零方差特征(相同值),即那些在所有的样本上的取值均不变的特征。

from sklearn.feature_selection import VarianceThreshold

X = [[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3], [0, 2, 3, 3]]
select = VarianceThreshold()
result = select.fit_transform(X)
print(result)
[[2 0]
 [1 4]
 [1 1]
 [2 3]]

VarianceThreshold 在上述代码中起的作用如下:

将第1列及第4列特征进行剔除而选择中间两列特征。

  • VarianceThreshold 类定义
def __init__(self, threshold=0.):
  • 参数说明

VarianceThreshold 对象在创建过程中可设置一个参数 threshold 。该参数定义了一个阈值,默认为0,如果手动设置了,则会删除训练集中方差低于该阈值的特征。

  • 实例

假设我们有一个特征是布尔值的数据集,我们想要移除那些在整个数据集中特征值为0或者为1的比例超过80%的特征。布尔特征是伯努利(Bernoulli)随机变量,变量的方差为 Var[X]=p(1p) Var[X] = p(1-p)
于是,整个代码如下:(第一列中值为0的概率为p=5/6>8)

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]]
select = VarianceThreshold(.8 * (1 - .8))
result = select.fit_transform(X)
print(result)
[[0 1]
 [1 0]
 [0 0]
 [1 1]
 [1 0]
 [1 1]]

2. 单变量特征选择

2.1 单变量特征选择工具类

单变量的特征选择,本质上是对每个变量(特征)进行一种检验,比如卡方检验,得到一个测试结果(分数)。根据这个分数来选择我们需要的特征。
常见的工具类有以下几种:

  • SelectKBest(self, score_func=f_classif, k=10): 用score_func指定的检验函数对每个特征进行检测,保留得分最高的k个(默认为10)
  • SelectPercentile(self, score_func=f_classif, percentile=10): 用score_func指定的检验函数对每个特征进行检测,保留前百分之几的特征,其中百分数由percentile指定(默认为%10)
  • SelectFpr(self, score_func=f_classif, alpha=5e-2): 根据FPR测试选择低于alpha的pvalues,其中FPR测试代表假阳性率测试,它控制错误检测的总量。
  • SelectFdr(score_func=f_classif, alpha=0.05): 选择估计的错误发现率的p值,其中alpha表示要保留的功能的最高未校正p值。
  • SelectFwe(score_func=f_classif, alpha=0.05): 选择与族系错误率对应的p值,其中alpha表示特征分数的p值
  • GenericUnivariateSelect(score_func=f_classif, mode=’percentile’, param=1e-05): 这是一个可配置的单变量特征选择器,用指定的score_func检验函数进行检验,之后根据mode指定的方式保留需要的特征,其中mode取值{‘percentile’, ‘k_best’, ‘fpr’, ‘fdr’, ‘fwe’},而param则为不同mode方式对应的参数

2.2 score_func参数说明

2.2.1 用于回归:

  • f_regression : 单变量线性回归

I=((X[:,i]mean(X[:,i]))(ymeany))/(std(X[:,i])std(y)) I = ((X[:, i] - mean(X[:, i])) * (y - mean_y)) / (std(X[:, i]) * std(y))

  • mutual_info_regression : 估算连续目标变量的互信息,互信息描述了两个变量之间的依赖关系,当且仅当两个随机变量是独立的时,其互信息值为0,当值越大时,依赖性越大。

I(X;Y)=YXp(x,y)log(p(x,y)p(x),p(y))dxdy I(X;Y) = \int_{Y} \int_{X}p(x,y)log({{p(x,y)}\over{p(x),p(y)}})dxdy

其中,p(x,y)是X和Y的联合概率密度函数,而p(x)与p(y)分别是X和Y的边缘概率密度函数。

2.2.2用于分类:

  • chi2 : 计算每个非负特征之间的卡方统计量。

X2=i=1k(finpi2)npi X^2 = \sum^k_{i=1}{({f_i-np_i}^2) \over np_i}

其中,假设总体分布为 F(x)F(x),且总体X的分布率为 P{X=xi}=pi,i=1,2,3,...P\{X=x_i\}=p_i,i=1,2,3,...

  • f_classif : 计算所提供样品的ANOVA F值(方差分析),这个函数是上述检验工具类的默认函数,它计算的是组间平均方差和组内平均方差的比值。
  • mutual_info_classif : 估计离散目标变量的互信息

I(X;Y)=yYxXlog(p(x,y)p(x),p(y)) I(X;Y) = \sum_{y \in Y} \sum_{x \in X}log({{p(x,y)}\over{p(x),p(y)}})

其中,p(x,y)是X和Y的联合概率分布函数,而p(x)与p(y)分别是X和Y的边缘概率分布函数。当离散变量变成了连续变量,求和计算则被积分替代。就变成了mutual_info_regression

3. 递归式特征消除

顾名思义,递归特征消除就是先将最不重要的特征剔除得到子集,再在子集的基础上,再把最不重要的剔除,得到更小的子集,如此递归下去,直到得到满足需要的特征子集。而在此过程中,对于特征的重要程度,则从 coef_ 属性和 feture_importances_ 属性获得。

  • 实例
from sklearn.svm import SVC
from sklearn.datasets import load_digits
from sklearn.feature_selection import RFE
import matplotlib.pyplot as plt

# Load the digits dataset
digits = load_digits()
X = digits.images.reshape((len(digits.images), -1))
y = digits.target
print("变量X的维度:")
print(X.shape)

# Create the RFE object and rank each pixel
svc = SVC(kernel="linear", C=1)
rfe = RFE(estimator=svc, n_features_to_select=1, step=1)
rfe.fit(X, y)
ranking = rfe.ranking_.reshape(digits.images[0].shape)
print("变量ranking的维度:")
print(ranking.shape)

# Plot pixel ranking
plt.matshow(ranking)
plt.colorbar()
plt.title("Ranking of pixels with RFE")
plt.show()
变量X的维度:
(1797, 64)
变量ranking的维度:
(8, 8)

在这里插入图片描述

4. SelectFromModel

首先,SelectFromModel 是为了处理来自于Model的数据而提出来的,如果相关的 coef_ 或者 featureimportances 属性值低于预先设置的阈值(threshold),这些特征将会被认为不重要并且移除掉。除了能够指定threshold的值外,还可以通过给定字符串参数来使用内置的启发式方法找到一个合适的阈值。

  • 实例
import matplotlib.pyplot as plt
import numpy as np

from sklearn.datasets import load_boston
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LassoCV

# Load the boston dataset.
boston = load_boston()
X, y = boston['data'], boston['target']

# We use the base estimator LassoCV since the L1 norm promotes sparsity of features.
clf = LassoCV(cv=5)

# Set a minimum threshold of 0.25
sfm = SelectFromModel(clf, threshold=0.25)
sfm.fit(X, y)
n_features = sfm.transform(X).shape[1]

# 修改threshold值
while n_features > 2:
    sfm.threshold += 0.1
    X_transform = sfm.transform(X)
    n_features = X_transform.shape[1]

# 绘制来自于X的两个特征变量的散点图
plt.title(
    "Features selected from Boston using SelectFromModel with "
    "threshold %0.3f." % sfm.threshold)
feature1 = X_transform[:, 0]
feature2 = X_transform[:, 1]
print("变量X的维度:")
print(X.shape)
print("选择后数据的维度:")
print(X_transform.shape)
plt.plot(feature1, feature2, 'r.')
plt.xlabel("Feature number 1")
plt.ylabel("Feature number 2")
plt.ylim([np.min(feature2), np.max(feature2)])
plt.show()
变量X的维度:
(506, 13)
选择后数据的维度:
(506, 2)

在这里插入图片描述

4.1 基于 L1 的特征选取

Linear models 使用 L1 正则化的线性模型会得到稀疏解:他们的许多系数为 0。

from sklearn.svm import LinearSVC
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
iris = load_iris()
X, y = iris.data, iris.target
print("X.shape")
print(X.shape)
lsvc = LinearSVC(C=0.01, penalty="l1", dual=False).fit(X, y)
model = SelectFromModel(lsvc, prefit=True)
X_new = model.transform(X)
print("X_new.shape")
print(X_new.shape)
X.shape
(150, 4)
X_new.shape
(150, 3)

4.2 基于 Tree(树)的特征选取

基于树的特征选取可以用来计算特征的重要性,然后可以消除不相关的特征。

  • 实例
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
iris = load_iris()
X, y = iris.data, iris.target
print("X.shape")
print(X.shape)
clf = ExtraTreesClassifier()
clf = clf.fit(X, y)
print("clf.feature_importances_")
print(clf.feature_importances_)
model = SelectFromModel(clf, prefit=True)
X_new = model.transform(X)
print("X_new.shape")
print(X_new.shape)
X.shape
(150, 4)
clf.feature_importances_
[0.03024885 0.04546254 0.43126586 0.49302275]
X_new.shape
(150, 2)

5. 特征选取作为 pipeline(管道)的一部分

特征选择通常在实际的学习之前用来做预处理。在 scikit-learn 中推荐的方式是使用 sklearn.pipeline.Pipeline

clf = Pipeline([
  ('feature_selection', SelectFromModel(LinearSVC(penalty="l1"))),
  ('classification', RandomForestClassifier())
])
clf.fit(X, y)

在这段代码中,我们利用 sklearn.svm.LinearSVC 和 sklearn.feature_selection.SelectFromModel 来评估特征的重要性并且选择出相关的特征。 然后,在转化后的输出中使用一个 sklearn.ensemble.RandomForestClassifier 分类器,比如只使用相关的特征。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章