从现有的m个特征中选出n个特征(n<=m),降低特征维度减少计算量的同时,使模型效果达到最优。
在实际业务中,用于模型中的特征维度往往很高,几万维。如一些CTR预估问题中,特征维度高达上亿维,维度过高会增大模型计算复杂度。但实际情况是,并不是每个特征对模型的预测都是有效果的,所以需要去除一些不必要的特征,从而降低模型计算的复杂度。
如果方差很小,说明该特征的取值很稳定,可以近似理解成该特征的每个值都接近。这样的特征对模型几乎是没有效果,不具备区分度的。比如年龄这个特征,都是20岁左右大小的。反之,方差越大,则特征对模型的区分度越好。
指移除方差低于指定阈值的特征,即特征值变动幅度小于某个范围的特征。这一部分特征的区分度较差,可以移除。这里的阈值需要根据具体的业务场景进行设定。
from sklearn.feature_selection import VarianceThreshold
X = [[0, 2, 1], [1, 1, 0], [2, 3, 0], [3, 6, 1], [4, 2, 0], [5, 1, 1]]
print(X)
print("---------------")
sel = VarianceThreshold(threshold=1)
sel.fit_transform(X)
print(sel.fit_transform(X))
基于单一变量和目标y之间的关系,通过计算某个能够度量特征重要性的指标,选出重要性TopK的特征。
该特征选择方式实现如下:
SelectKBest(score_func=
其中score_func是用来指定特征重要性的计算公式,k是特征保留维度。
下面是一些score_func函数及其解释:
分类:chi2,f_classif,mutual_info_classif
回归:f_regression,mutual_info_regression
缺点:忽略了特征组合的情况。有的时候,单一特征的表现可能不是很好,但是与其他特征组合以后,效果就很不错,这样就会造成特征被误删,所以这种特征选择方式不常用。
递归式消除特征(RFE)是指,将全部特征都丢到给定的模型里面,模型会输出每个特征的重要性,然后删除那些不太重要的特征;把剩下的特征再次丢到模型里面,又会输出各个特征的重要性,再次删除;如此循环,直至最后剩下目标维度的特征值。
from sklearn.datasets import make_friedman1
from sklearn.feature_selection import RFE
from sklearn.svm import SVR
X, y = make_friedman1(n_samples=50, n_features=10, random_state=0)
estimator = SVR(kernel="linear")
##5个特征被选中,每次迭代去除1个特征。
selector = RFE(estimator, 5, step=1)
selector = selector.fit(X, y)
print(selector.support_) ##所选特征的掩码
##特征排名,使得rank_ [i]对应于第i个特征的排名位置。
##所选择的(重要性最高的)特征被分配为等级1,被删除的特征显示其原始的位置。
selector.ranking_
print(selector.fit(X,y))
缺点:
SelectFromModel可以用来处理任何带有coef_或者feature_importances_ 属性的训练之后的模型。
如果相关的coef_ 或者 feature_importances 属性值低于预先设置的阈值,这些特征将会被认为不重要并且移除掉。除了指定数值上的阈值之外,还可以通过给定字符串参数来使用内置的启发式方法找到一个合适的阈值。可以使用的启发式方法有 mean 、 median 以及使用浮点数乘以这些(例如,0.1*mean )
SelectFromModel和递归式消除特征不同的是,该方法不需要重复训练模型,只需要训练一次即可;二是该方法是指定权重的阈值,不是指定特征的维度。
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
lsvc = LinearSVC(C=0.01, penalty="l1", dual=False).fit(X, y)
model = SelectFromModel(lsvc, prefit=True)
X_new = model.transform(X)
X_new.shape
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
clf = ExtraTreesClassifier()
clf = clf.fit(X, y)
clf.feature_importances_
model = SelectFromModel(clf, prefit=True)
X_new = model.transform(X)
X_new.shape