高效特征选择:优化机器学习的嵌入式方法指南
文章目录
- 一、说明
- 二、特征选择方法
- 三、嵌入式方法
- 四、Lasso正则化
- 五、Python 中的 Lasso 实现
- 六、决策树的特征重要性
- 七、Python 实现
- 八、嵌入式方法和递归特征消除
- 九、结论
一、说明
假设您正在处理一个大型数据集,并且想要训练一个机器学习算法。挑战在于决定从众多变量中应该考虑哪些特征来构建有效的模型。这就是特征选择发挥作用的地方,它使我们能够筛选数据混乱并创建更易于解释和更强大的模型。
特征选择包括从数据集中选择一组特征来训练机器学习算法。特征选择过程的目的是减少特征数量,从而提高可解释性和模型的弹性。
特征选择方法可以分为三类:过滤方法、包装方法和嵌入方法。
二、特征选择方法
过滤方法是一种与模型无关的特征选择技术,它根据数据的特征选择特征,与机器学习模型无关。它们的计算成本最低,包括卡方检验和皮尔逊相关系数等。
包装器方法是一种围绕预测模型进行搜索的特征选择算法。它们生成多个特征子集,在每个子集上训练分类或回归模型(迭代),并确定其性能。
包装方法的计算成本最高。包装方法的示例包括前向选择、后向消除和穷举搜索。
嵌入式方法将选择过程“嵌入”到预测模型的训练中。对最佳特征子集的搜索内置于分类器或回归算法的训练中。因此,嵌入式方法仅训练一个机器学习模型来选择特征。它们的计算成本等于模型训练时间。
在这篇博文中,我们将重点介绍嵌入式方法。
三、嵌入式方法
嵌入式方法将选择“嵌入”到模型构建阶段。典型的嵌入式特征选择工作流程包括:
训练机器学习模型。
得出特征重要性。
选择排名靠前的预测变量。
最常见的嵌入策略是线性模型中的 Lasso 正则化和从决策树中的信息增益获得的特征重要性。
但请注意,并非所有机器学习模型都能自然地嵌入特征选择过程。例如,支持向量机 (svm) 就不能。
四、Lasso正则化
线性回归模型根据特征空间的线性组合来预测结果。系数是通过最小化目标的实际值和预测值之间的平方差来确定的。
主要有三种正则化程序:Ridge正则化、Lasso正则化,以及结合前两者的弹性网络。
在 Lasso 回归中,系数会以给定的常数缩小。在 Ridge 回归中,系数的平方会受到一个常数的惩罚。缩小系数的目的是为了减少偏差并防止过拟合。最佳常数需要通过超参数优化来估计。
事实证明,Lasso 正则化能够将某些系数设置为零。然后,我们可以安全地从数据中删除这些特征。
在下图中,我们可以看到随着正则化惩罚的增加,系数的变化。随着惩罚的增加,越来越多的系数被设置为零。
相比之下,Ridge 正则化不具备该属性,或者至少在惩罚非常大之前不具备该属性,如下图所示:
更强的正则化可以带来更大的维数降低。
五、Python 中的 Lasso 实现
让我们看看如何使用 Python 中的 Lasso 选择相关特征。让我们导入库、函数和类:
import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import Lasso, LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
让我们从 Scikit-learn 导入乳腺癌数据集并将其分成训练集和测试集:
breast_cancer = load_breast_cancer()
X = pd.DataFrame(breast_cancer.data, columns=breast_cancer.feature_names)
y = breast_cancer.target
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
让我们设置一个缩放器来标准化特征:
scaler = StandardScaler()
scaler.fit(X_train)
接下来,我们将利用带有 Lasso 正则化的逻辑回归来选择特征:
sel_ = SelectFromModel(
LogisticRegression(
C=0.5, penalty='l1', solver='liblinear', random_state=10),
)
sel_.fit(scaler.transform(X_train), y_train)
通过执行,sel_.get_support()我们获得一个布尔向量,其中具有非零系数的特征为 True:
array([False, True, False, False, False, False, False, True, True,
False, True, False, False, False, False, True, False, False,
False, True, True, True, True, True, True, False, True,
True, True, False])
我们可以像这样识别已删除功能的名称:
removed_feats = X_train.columns[(sel_.estimator_.coef_ == 0).ravel().tolist()]
如果我们执行,removed_feats我们将获得以下包含将被删除的特征的数组:
Index(['mean radius', 'mean perimeter', 'mean area', 'mean smoothness',
'mean compactness', 'mean concavity', 'mean fractal dimension',
'texture error', 'perimeter error', 'area error', 'smoothness error',
'concavity error', 'concave points error', 'symmetry error',
'worst compactness', 'worst fractal dimension'],
dtype='object')
我们可以像这样从训练和测试集中删除这些特征:
X_train_selected = sel_.transform(scaler.transform(X_train))
X_test_selected = sel_.transform(scaler.transform(X_test))
如果我们现在执行:
X_train_selected.shape, X_test_selected.shape
我们获得了缩减后的数据集的形状:
((426, 14), (143, 14))
六、决策树的特征重要性
决策树算法通过对数据进行连续分区来预测结果。在每个节点上,选择一个特征和一个值来进行分区。最好的分区是最大限度地减少杂质的分区。
有多种指标可用于确定“杂质”。在分类中,算法会最小化基尼系数或熵。在回归中,算法会最小化均方误差(如最小二乘法)、平均绝对误差或泊松偏差。
每个特征的重要性由整个树中杂质的总减少量决定。例如,如果某个特征用于划分节点 1 中的数据,然后又用于划分节点 3 中的数据,则该特征的重要性由两个节点的杂质减少量之和决定。
随机森林会同时生长出许多分类树,预测结果为各个分类树的平均值。因此,特征重要性由各个分类树的平均重要性决定。
相反,梯度提升机(如 xgboost)会构建顺序树,以最小化树的预测与前一棵树的残差之间的差异。这里,特征重要性是树间重要性的总和。
然后我们可以选择最重要的特征。
七、Python 实现
让我们从基于决策树的模型中选择最重要的特征。我们将使用随机森林和乳腺癌数据集。
让我们首先导入库、函数和类:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectFromModel
from sklearn.model_selection import train_test_split
让我们加载数据集并将其分成训练集和测试集:
breast_cancer = load_breast_cancer()
X = pd.DataFrame(breast_cancer.data, columns=breast_cancer.feature_names)
y = breast_cancer.target
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
让我们根据随机森林分类器得出的重要性来选择特征:
sel_ = SelectFromModel(RandomForestClassifier(n_estimators=10, random_state=10))
sel_.fit(X_train, y_train)
SelectFromModel将选择重要性大于所有特征平均重要性的特征。这可以通过参数 进行修改threshold。
我们sel_.get_support()获得一个True表示所选特征的布尔向量:
array([ True, False, False, True, False, False, True, True, False,
False, True, False, False, False, False, False, False, False,
False, False, False, False, True, True, False, False, False,
True, False, False])
我们可以将选定的特征列出如下列表:
selected_feat = X_train.columns[(sel_.get_support())]
通过执行len(selected_feat)我们获得所选特征的数量:8。通过执行selected_feat我们获得所选变量的名称:
Index(['mean radius', 'mean area', 'mean concavity', 'mean concave points',
'radius error', 'worst perimeter', 'worst area',
'worst concave points'],
dtype='object')
让我们绘制特征重要性:
pd.Series(
sel_.estimator_.feature_importances_.ravel(),
index=X_train.columns).plot.bar(figsize=(10,5),
)
plt.ylabel('Feature importance')
plt.show()
下面我们看到随机森林赋予每个特征的重要性:
最后,我们可以将数据集缩减为选定的变量:
X_train_selected = sel_.transform(X_train)
X_test_selected = sel_.transform(X_test)
就是这样,我们现在已经根据从决策树获得的重要性选择了特征。
八、嵌入式方法和递归特征消除
线性回归或决策树得出的重要性受相关性影响。共线性通常会降低重要性值。因此,为了避免删除相关特征(这些特征可能比与其他任何特征无关的其他特征更重要),我们倾向于将嵌入式方法与递归特征消除相结合。
在递归特征消除中,我们在删除一个或多个不相关的特征后重新训练模型,因此,如果删除了相关特征,剩下的相关特征将显示出更大的重要性。
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import RFE
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
# Load iris dataset
url = "https://gist.githubusercontent.com/curran/a08a1080b88344b0c8a7/raw/0e7a9b0a5d22642a06d3d5b9bcbad9890c8ee534/iris.csv"
df = pd.read_csv(url)
# Separate features and target variable
X = df.drop("species", axis=1)
y = df["species"]
# Initialize RandomForestClassifier
model = RandomForestClassifier()
# Initialize RFE
rfe = RFE(estimator=model, n_features_to_select=1)
# Fit RFE
rfe.fit(X, y)
# Print the ranking
ranking = rfe.ranking_
print("Feature ranking:")
for i, feature in enumerate(X.columns):
print(f"{feature}: {ranking[i]}")
输出:
特征排名:
sepal_length: 3
sepal_width: 4
petal_length: 2
petal_width: 1
九、结论
总之,嵌入式方法提供了一种强大而有效的特征选择方法,将选择过程无缝集成到模型训练本身中。与包装器方法相比,这不仅降低了计算复杂性,而且还确保了特征选择本质上与模型的预测能力保持一致。诸如线性模型的 Lasso 正则化和基于树的方法中的特征重要性等技术使我们能够识别并仅保留最相关的特征,从而提高模型性能和可解释性。
然而,必须考虑共线性等潜在缺陷,因为共线性可能会掩盖某些特征的重要性。将嵌入式方法与递归特征消除相结合可以缓解此问题,从而提供更全面的特征选择过程。通过采用这些方法,您可以构建更高效、可扩展且准确的机器学习模型,同时保持特征空间的简单性。