Feature Engineering, 称之为特征工程,属于机器学习中数据预处理阶段的重要内容,细分为以下两大类内容 1. Feature Extraction, 特征提取,从文本,图像等原始数据中提取可以用于建模的特征 2. Feature Selection, 特征选择,从原始数据中的多维特征中筛选最优特征自己,达到降维,提升模型准确性,减少运行时间等效果 特征选择的策略可以分为以下3大类 1. Filter 根据某项指标的阈值对特征进行过滤,常见的有以下三种方法 1. 方差 2. 相关系数 3. 卡方检验 方差表征数据的发散程度,方差越大,数据分布越发散。对于分类数据而言,特征对应的数据分布越集中,对分类器的贡献越小,所以会删除方差较小的特征。在scikit-learn中,可以通过如下方式指定方差阈值,删除低方差对应的特征 >>> 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]] >>> sel = VarianceThreshold(threshold=(.8 * (1 - .8))) >>> sel.fit_transform(X) array([[0, 1], [1, 0], [0, 0], [1, 1], [1, 0], [1, 1]]) 相关系数表征两个连续性变量之间的线性相关性,比如经典的pearson相关系数,适用于两个服从高斯分布的连续变量,相关系数越接近0,两个变量的相关性越弱。对于回归类问题,可以根据自变量与因变量的相关性,去除相关系数低的特征。
卡方检验适用于两个离散型变量之间的关联程度,可以用于筛选分类问题中的离散自变量。 2. Wrapper 封装类的方法是将特征选择和机器学习模型合并到一起来考虑,通过迭代使用不同的特征组合来训练机器学习的模型,根据模型的效果来筛选对应的特征。根据迭代的方式,分为以下3类 1. 前向选择法,放入模型的特征依次增多,每次循环放入能最大限度提升模型效果的特征,直到任何特征都不能提升模型表现 2. 后向选择法,与前向选择法相反,第一次循环就放入所有特征,然后每次循环,剔除最不显著的特征,直到模型收敛 在实践中,最常用的是递归特征消除法,全称如下 recursive feature elimination
简称RFE,策略上属于后向选择,通过递归逐步减少特征来进行筛选。首先,采用所有特征进行训练,训练完成后每个特征对应一个权重,然后去掉权重最小的特征,用剩余的特征在进行训练,重复上述步骤,直到剩余的特征数量达到所需的特征数量。在scikit-learn中,使用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") >>> selector = RFE(estimator, n_features_to_select=5, step=1) >>> selector = selector.fit(X, y) >>> selector.support_ array([ True, True, True, True, True, False, False, False, False, False]) >>> selector.ranking_ array([1, 1, 1, 1, 1, 6, 4, 3, 2, 5]) 在该算法中,需要人为指定所需的特征数量值。为了克服这个超参数的设置问题,scikit-learn中支持采用交叉验证的方式,对于特征的所有组合,计算所有组合的误差,选择误差最小的特征集合作为所挑选的特征,用法如下
>>> from sklearn.feature_selection import RFECV >>> from sklearn.svm import SVR >>> X, y = make_friedman1(n_samples=50, n_features=10, random_state=0) >>> estimator = SVR(kernel="linear") >>> selector = RFECV(estimator, step=1, cv=5) >>> selector = selector.fit(X, y) >>> selector.support_ array([ True, True, True, True, True, False, False, False, False, False]) >>> selector.ranking_ array([1, 1, 1, 1, 1, 6, 4, 3, 2, 5]) 嵌入式的策略也会用到机器学习的模型,但是和封装类不同的是,这里只训练一次,然后根据特征的权重直接进行筛选,所以速度更快。最常用的方法有以下两种 1. 基于正则项的模型 2. 基于随机森林的模型 以L1正则项为例,在其模型中会有很多系数为0的特征,我们可以通过筛选非零特征来进行特征筛选。在scikit-learn中,使用L1正则项来筛选特征的代码如下 >>> from sklearn.datasets import load_iris >>> from sklearn.feature_selection import SelectFromModel >>> X, y = load_iris(return_X_y=True) >>> X.shape (150, 4) >>> 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 (150, 3) 在随机森林模型中,可以将不纯度减少的平均值作为特征重要性的衡量指标,以此来筛选特征。随机森林由多颗决策树组成,决策树节点在分裂时,考虑的该特征对树的不纯度的减少程度,对于随机森林,计算的则是多颗树的平均值。在scikit-learn中,使用平均不纯度减少来筛选特征的代码如下 >>> from sklearn.datasets import load_iris >>> from sklearn.feature_selection import SelectFromModel >>> X, y = load_iris(return_X_y=True) >>> X.shape (150, 4) >>> clf = ExtraTreesClassifier(n_estimators=50) >>> clf = clf.fit(X, y) >>> clf.feature_importances_ array([ 0.04..., 0.05..., 0.4..., 0.4...]) >>> model = SelectFromModel(clf, prefit=True) >>> X_new = model.transform(X) >>> X_new.shape (150, 2) 对于机器学习而言,数据和特征决定了其上上限,模型和算法只是逼近这个上限而已。要掌握机器学习,除了经典的机器学习模型和算法,还需要对特征工程的相关策略进行了解和学习。
|