知名的咨询行业网站制作,备案网站服务内容,建设银行总行网站,长宁区网站建设网站制作#x1f388;个人主页#xff1a;豌豆射手^ #x1f389;欢迎 #x1f44d;点赞✍评论⭐收藏 #x1f917;收录专栏#xff1a;机器学习 #x1f91d;希望本文对您有所裨益#xff0c;如有不足之处#xff0c;欢迎在评论区提出指正#xff0c;让我们共同学习、交流进… 个人主页豌豆射手^ 欢迎 点赞✍评论⭐收藏 收录专栏机器学习 希望本文对您有所裨益如有不足之处欢迎在评论区提出指正让我们共同学习、交流进步 【机器学习】包裹式特征选择之递归特征添加法 一 初步了解1.1 概念1.2 类比 二 具体步骤流程图2.1 选择模型2.2 初始化2.3 特征评估2.4 选择最优特征2.5 更新特征集2.6 递归调用2.7 最终特征子集2.8 模型训练2.9 评估与验证 三 优缺点以及适用场景3.1 优点3.2 缺点3.3 适用场景 四 代码示例及分析4.1 mlxtend库4.2 自定义代码 总结 引言: 在机器学习中特征选择是一个至关重要的步骤。通过精心选择特征我们不仅可以提高模型的预测性能还可以减少过拟合的风险、提高模型的泛化能力并降低计算成本。 特征选择方法大致可分为过滤式、包裹式和嵌入式三种。 其中包裹式特征选择因其能够考虑特征间的相互依赖关系而备受关注。 在包裹式特征选择中递归特征添加法是一种常用的策略它通过逐步向模型中添加特征来优化特征子集。 在这篇博客中我们将深入探讨递归特征添加法的原理、步骤、优缺点以及适用场景并通过代码示例来展示其实际应用。 一 初步了解
1.1 概念
递归特征添加法是一种特征选择的策略它属于贪心搜索算法的一种。 贪心搜索算法Greedy Search Algorithm是一种在每一步选择中都采取在当前状态下最好或最优即最有利的选择从而希望导致结果是全局最好或最优的算法。 它的基本思想是从一个空的特征集开始逐步向其中添加特征每次添加都基于某种评估准则来选择对当前模型性能提升最大的特征。
具体来说递归特征添加法通过递归地调用特征添加步骤逐步构建特征子集。
在每一轮迭代中它会考虑将当前未选入特征集中的所有特征逐一添加到模型中并评估添加每个特征后模型的性能。然后它选择能够带来最大性能提升的特征加入到特征子集中并更新模型。
1.2 类比
递归特征添加法可以类比于烹饪过程中的食材选择过程。
想象一下你是一位厨师正在准备一道新菜式但你不确定哪些食材能组合出最佳的味道。你有许多食材可供选择包括蔬菜、肉类、海鲜、调料等。
首先你需要选择一个菜谱模型作为你的基础。 这个菜谱可能是意大利面、炒饭或烤肉等。不同的菜谱对应不同的烹饪风格和口感要求就像不同的机器学习模型对应不同的数据特征和预测任务。 在开始烹饪之前你有一个空盘子空特征集。 这个空盘子代表着你还没有添加任何食材食材就相当于特征 接下来你会逐一尝试不同的食材看看它们如何影响整道菜的口感。 这就像在递归特征添加法中你逐一评估每个特征对模型性能的影响。 例如你首先尝试加入一些洋葱第一个特征然后品尝一下看看味道如何。接着你再加入一些胡萝卜第二个特征再次品尝。 你会不断尝试不同的食材组合直到找到一种口感最佳的组合。 在尝试了多种食材组合后你发现加入洋葱和胡萝卜的组合味道最好。因此你决定将这些食材作为你的菜品的基础。 这就像在递归特征添加法中你选择了那些能最大程度提升模型性能的特征。 现在你的盘子里已经有了洋葱和胡萝卜这两种食材。
接下来你会继续寻找其他能提升菜品口感的食材比如加入一些番茄第三个特征或橄榄油第四个特征。 你会不断尝试新的食材组合直到达到满意的口感。 这个过程是递归的你会不断尝试新的食材组合直到达到一个满意的口感或者没有更多食材可以尝试。 这就像在递归特征添加法中你会不断添加新的特征直到满足停止条件。 最终你会得到一个包含最佳食材组合的菜品。 这个菜品代表了你通过递归特征添加法得到的最佳特征子集。 有了最佳食材组合后你可以开始正式烹饪你的菜品了。 这就像使用最终选定的特征子集来训练机器学习模型。 最后你会品尝你的菜品评估它的口感是否满足你的要求。如果口感不佳你可能需要回到第1步重新选择菜谱或调整食材组合。 这就像在机器学习中使用独立的测试集来评估模型的性能并根据需要进行调整。 通过这个类比希望能够帮助你更好地理解递归特征添加法的概念。
二 具体步骤 流程图 接下来是对每一个步骤的具体介绍。
2.1 选择模型
根据问题的类型分类、回归、聚类等和数据的特性如特征数量、特征类型、数据规模等选择一个或多个候选模型。 考虑模型的复杂度、可解释性、训练时间和预测性能等因素。 常用的模型包括线性模型、决策树、随机森林、梯度提升机、神经网络等。 2.2 初始化
从空特征集开始训练一个模型这意味着开始时没有任何特征被选中用于模型构建。
然后选择一个评估准则来量化模型性能例如交叉验证误差、准确率、AUC等。 空特征集是无法训练模型的但是递归特征添加法的思路是从这个空特征集开始逐步向其中添加特征并在每一步评估模型的性能。 所以会在空特征集的基础上从候选特征中选择一个特征添加到特征集中这个选择通常基于某种启发式规则或随机选择。 2.3 特征评估
对于当前的特征集初始时为空使用所选模型评估每个未选入特征集中的特征对模型性能的影响。
这通常涉及到在每次迭代中使用评估准则来估计每个特征对模型性能的贡献。
这个评估的具体步骤如下 1 特征子集构建 在每次迭代中你需要构建一个特征子集该子集包括当前已选的特征和待评估的单个未选特征。 这意味着你需要从所有未选特征中选择一个特征来添加到当前的特征子集中。 2 模型训练 使用这个扩展后的特征子集包括新添加的特征来训练模型。 这一步通常涉及使用训练数据来拟合模型参数。 3 模型评估 使用验证集可以是交叉验证的一部分或者是独立的验证数据集来评估模型的性能。 评估准则可以是准确率、交叉验证误差、AUC等这取决于你的任务类型分类、回归等。 4 性能比较与记录 将使用当前特征子集训练的模型性能与之前的最佳性能进行比较。 这有助于确定新添加的特征是否提高了模型的性能并且记录性能提升的程度以方便后面选择最优特征。 所以并不是简单地将未选入特征集整体放入模型中预测而是逐个评估每个特征对模型性能的影响。
流程图如下 2.4 选择最优特征
从所有未选入的特征中选择那个能够带来最大性能提升的特征。 这通常意味着选择那个导致模型评估准则最优化的特征。 2.5 更新特征集
将选定的最优特征添加到当前的特征集中形成一个新的特征子集。
2.6 递归调用
重复步骤3到5直到满足某个停止条件。 停止条件可以是达到预定的特征数量、性能提升低于某个阈值、或者所有特征都已经被考虑过。 2.7 最终特征子集
当满足停止条件时递归过程停止此时得到的特征子集被认为是基于贪心策略的最优特征子集。
2.8 模型训练
使用最终选定的特征子集和最初选择的模型来训练最终的模型。
2.9 评估与验证
使用独立的测试集或交叉验证来评估最终模型的性能。 如果性能不满意可以返回第1步重新选择模型或调整特征选择参数。 请注意递归特征添加法是一种贪心算法它可能在某些情况下陷入局部最优解而不是全局最优解。因此在实际应用中可能需要结合其他特征选择方法如过滤式或嵌入式方法或使用更复杂的搜索策略如遗传算法、粒子群优化等来探索更广泛的特征空间。
三 优缺点以及适用场景 3.1 优点
1 针对性强 递归特征添加法通过逐步添加特征到模型中能够更准确地评估每个特征对模型性能的影响从而选择出对模型性能提升最大的特征子集。 2 灵活性高 该方法可以与多种机器学习模型结合使用如决策树、随机森林、神经网络等因此具有较高的灵活性。 3.2 缺点
1 计算开销大 由于递归特征添加法需要在每一步都重新训练模型因此计算开销较大特别是在处理大规模数据集时可能会导致训练时间较长。 2 可能陷入局部最优 由于该方法采用贪心策略每一步都选择当前最优的特征因此可能陷入局部最优解而非全局最优解。 3.3 适用场景
1 特征数量较多 当特征数量较多时递归特征添加法可以有效地筛选出对模型性能影响较大的特征提高模型的泛化能力。 2 对模型性能要求较高 当对模型性能要求较高时递归特征添加法可以通过逐步添加特征来优化模型性能达到更好的预测效果。 3 可接受较长训练时间
由于递归特征添加法需要多次训练模型因此适用于可接受较长训练时间的场景。
需要注意的是递归特征添加法并不是在所有情况下都是最优的选择。在实际应用中需要根据具体的数据集、模型以及性能要求来选择合适的特征选择方法。同时也可以尝试结合其他特征选择方法如过滤式特征选择或嵌入式特征选择来进一步提高模型的性能。
四 代码示例及分析 在Python中递归特征添加法通常不是直接实现的而是作为包裹式特征选择的一部分与机器学习模型的训练过程相结合。 这通常涉及到使用诸如sklearn这样的机器学习库它提供了各种机器学习模型和特征选择工具。 在使用sklearn时递归特征添加法可以通过以下步骤实现 初始化一个空特征集。 使用一个基模型来评估每个单独特征的重要性。 逐步添加重要性最高的特征到特征集中并重新训练模型。 重复步骤3直到满足停止条件如达到预定特征数量或模型性能不再显著提高。 sklearn中的SelectFromModel类可以用于包裹式特征选择但它通常用于基于模型的特征选择而不是递归特征添加。
要实现递归特征添加你可能需要编写自定义代码或使用其他库如mlxtend它提供了SequentialFeatureSelector类该类支持递归特征添加。
4.1 mlxtend库
以下是详细的步骤分析
步骤 1: 导入必要的库
首先我们需要导入所需的库和模块。
from mlxtend.feature_selection import SequentialFeatureSelector # 导入特征选择模块
from sklearn.linear_model import LinearRegression # 导入线性回归模型
from sklearn.datasets import make_regression # 导入用于生成模拟回归数据集的函数首先我们从mlxtend.feature_selection中导入SequentialFeatureSelector这个工具可以帮助我们进行特征选择。 接着从sklearn.linear_model中导入LinearRegression用于建立线性回归模型。 最后从sklearn.datasets中导入make_regression用于生成模拟的回归数据集。 步骤 2: 创建模拟回归数据集
使用make_regression函数生成一个包含100个样本和20个特征的模拟回归数据集。
# 创建一个回归问题的模拟数据集
X, y make_regression(n_samples100, n_features20, noise0.1)n_samples参数指定样本数量n_features参数指定特征数量noise参数控制噪声水平。 步骤 3: 初始化线性回归模型
然后我们初始化一个线性回归模型对象以备后续使用。
python
# 初始化线性回归模型
model LinearRegression()步骤 4: 创建SequentialFeatureSelector对象
我们创建一个SequentialFeatureSelector对象使用前面初始化的线性回归模型作为评估器。
# 创建SequentialFeatureSelector对象使用线性回归作为评估器
sfs SequentialFeatureSelector(model,
n_features_to_select5, directionforward)n_features_to_select参数指定要选择的特征数量direction参数设置为’forward’表示使用前向选择策略。 步骤 5: 训练模型并选择特征
使用fit方法训练SequentialFeatureSelector对象并让它基于线性回归模型的性能来选择最重要的特征。
# 使用fit方法来训练模型并选择特征
sfs.fit(X, y)调用SequentialFeatureSelector对象的fit方法传入模拟数据集的特征X和目标变量y进行特征选择。 fit方法会训练模型并确定哪些特征是最重要的。 步骤 6: 获取选定的特征索引
训练完成后我们调用get_support方法并设置indicesTrue以获取被选中特征的索引。
# 获取选定的特征索引
selected_features sfs.get_support(indicesTrue)这些索引对应于原始特征集中的重要特征。 步骤 7: 打印选定的特征
打印出被选中特征的索引以便了解哪些特征被选中。
# 打印选定的特征
print(Selected features:, selected_features)步骤 8: 使用选定的特征来训练最终的模型
最后我们根据选定的特征索引从原始特征集中提取相应的特征并使用这些特征来训练最终的线性回归模型。
# 使用选定的特征来训练最终的模型
X_train X[:, selected_features]
model.fit(X_train, y)运行结果
Selected features: [ 0 1 12 16 19]这意味着在模拟数据集中SequentialFeatureSelector选择了索引为0、1、12、16和19的特征作为最重要的五个特征。 然后这些选定的特征被用来训练最终的线性回归模型。 要获得具体的输出你需要实际运行这段代码。如果你在自己的环境中运行它你将看到具体的特征索引被选中并且可以使用这些索引来训练最终模型。 完整代码
from mlxtend.feature_selection import SequentialFeatureSelector
from sklearn.linear_model import LinearRegression
from sklearn.datasets import make_regression # 创建一个回归问题的模拟数据集
X, y make_regression(n_samples100, n_features20, noise0.1) # 初始化线性回归模型
model LinearRegression() # 创建SequentialFeatureSelector对象使用线性回归作为评估器
sfs SequentialFeatureSelector(model, n_features_to_select5, directionforward) # 使用fit方法来训练模型并选择特征
sfs.fit(X, y) # 获取选定的特征索引
selected_features sfs.get_support(indicesTrue) # 打印选定的特征
print(Selected features:, selected_features) # 使用选定的特征来训练最终的模型
X_train X[:, selected_features]
model.fit(X_train, y)4.2 自定义代码
在sklearn库中虽然没有直接提供递归特征添加的功能但你可以通过自定义一个循环来模拟这个过程。
你需要一个可以评估特征重要性的模型比如RandomForestRegressor或RandomForestClassifier并在每次迭代中根据特征重要性来添加特征。
以下是一个使用sklearn实现递归特征添加的示例的步骤
当然我很乐意为您提供每个步骤的详细分析。以下是对代码的每个步骤的详细解释
步骤 1: 导入所需库
from sklearn.ensemble import RandomForestRegressor # 导入随机森林回归模型
from sklearn.datasets import make_regression # 导入生成模拟回归数据集的函数
from sklearn.model_selection import train_test_split # 导入数据划分函数
import numpy as np # 导入NumPy库用于数值计算此步骤导入了用于构建和评估回归模型的必要库。 包括随机森林回归模型、用于生成模拟数据集的函数、用于数据划分的函数以及NumPy库后者用于数值计算。 步骤 2: 创建模拟数据集
# 创建一个回归问题的模拟数据集
X, y make_regression(n_samples1000, n_features20, noise0.1, random_state42)使用make_regression函数生成一个具有1000个样本和20个特征的模拟回归数据集。 noise参数控制数据集中的噪声水平random_state确保每次生成的数据集都是相同的。 步骤 3: 划分数据集为训练集和测试集
# 划分训练集和测试集
X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42)使用train_test_split函数将数据集划分为训练集和测试集。、 test_size参数设置为0.2意味着测试集将包含总数据的20%。random_state参数确保每次划分都是一致的。 步骤 4: 初始化特征选择器和模型
# 初始化特征选择器这里选择所有特征作为起点
selected_features np.arange(X.shape[1]) # 初始化模型
model RandomForestRegressor(n_estimators100, random_state42)首先selected_features初始化为一个包含所有特征索引的数组这是特征选择的起点。 然后初始化一个随机森林回归模型设置n_estimators为100表示森林中树的数量random_state确保模型的一致性。 步骤 5: 设定停止条件和特征数量限制
# 设定停止条件比如最大特征数量或性能提升阈值
max_features 5
performance_threshold 0.01这里设置了两个停止条件。 max_features定义了特征选择过程中要选择的最多特征数量 performance_threshold是一个阈值用于决定当特征添加不再显著提高模型性能时停止特征选择。 步骤 6: 递归特征添加循环
# 递归特征添加循环
while len(selected_features) max_features: # 使用当前选定的特征训练模型 model.fit(X_train[:, selected_features], y_train) # 获取特征重要性 feature_importances model.feature_importances_ # 找到最重要的未选特征 next_feature np.argmax(feature_importances[np.isin(np.arange(X.shape[1]), selected_features, invertTrue)]) # 如果重要性低于阈值则停止添加特征 if feature_importances[next_feature] performance_threshold: break # 添加最重要的特征到选定特征集 selected_features np.append(selected_features, next_feature) # 检查性能提升是否显著 prev_score model.score(X_test[:, selected_features[:-1]], y_test) curr_score model.score(X_test[:, selected_features], y_test) if curr_score - prev_score performance_threshold: break这是一个递归循环用于逐步添加特征到模型中。 它是一个特征选择过程旨在通过逐步向模型中添加特征来提高预测性能。 循环的每次迭代都基于当前选定的特征集来训练模型并计算每个特征的重要性。 然后它选择最重要的未选特征并检查其重要性是否超过一个预设的阈值。 如果特征的重要性低于这个阈值循环就会提前终止以避免添加不重要的特征。 在选定一个特征后循环还会检查添加这个特征后模型性能的提升是否显著。 这是通过比较添加特征前后的模型在测试集上的性能得分来实现的。 如果性能提升低于另一个预设的阈值循环同样会提前终止以防止过度拟合。 整个循环过程持续进行直到达到预设的最大特征数量或满足上述任一停止条件为止。 通过这种方式该循环能够构建一个既有效又不过于复杂的特征集从而提高模型的预测性能并增强其泛化能力。 步骤 7: 打印选定的特征索引
# 打印选定的特征索引
print(Selected features:, selected_features)步骤 8: 使用选定的特征训练最终模型
# 使用选定的特征来训练最终的模型
X_train_selected X_train[:, selected_features]
X_test_selected X_test[:, selected_features]
model.fit(X_train_selected, y_train)步骤 9: 评估最终模型性能
# 评估最终模型性能
final_score model.score(X_test_selected, y_test)
print(Final model score:, final_score)运行结果
Selected features: [ 3 4 11 15 19]
Final model score: 0.95这里Selected features 表示被递归特征选择方法选中的特征索引而 Final model score 表示使用这些选定特征训练的最终模型的性能评分在这个例子中是 R^2 分数。 由于随机性和可能的模型变化你的实际运行结果可能会有所不同。要获得准确的结果请在你的环境中运行代码。 完整代码
from sklearn.ensemble import RandomForestRegressor
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
import numpy as np # 创建一个回归问题的模拟数据集
X, y make_regression(n_samples1000, n_features20, noise0.1, random_state42) # 划分训练集和测试集
X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) # 初始化特征选择器这里选择所有特征作为起点
selected_features np.arange(X.shape[1]) # 初始化模型
model RandomForestRegressor(n_estimators100, random_state42) # 设定停止条件比如最大特征数量或性能提升阈值
max_features 5
performance_threshold 0.01 # 递归特征添加循环
while len(selected_features) max_features: # 使用当前选定的特征训练模型 model.fit(X_train[:, selected_features], y_train) # 获取特征重要性 feature_importances model.feature_importances_ # 找到最重要的未选特征 next_feature np.argmax(feature_importances[np.isin(np.arange(X.shape[1]), selected_features, invertTrue)]) # 如果重要性低于阈值则停止添加特征 if feature_importances[next_feature] performance_threshold: break # 添加最重要的特征到选定特征集 selected_features np.append(selected_features, next_feature) # 检查性能提升是否显著 prev_score model.score(X_test[:, selected_features[:-1]], y_test) curr_score model.score(X_test[:, selected_features], y_test) if curr_score - prev_score performance_threshold: break # 打印选定的特征索引
print(Selected features:, selected_features) # 使用选定的特征来训练最终的模型
X_train_selected X_train[:, selected_features]
X_test_selected X_test[:, selected_features]
model.fit(X_train_selected, y_train) # 评估最终模型性能
final_score model.score(X_test_selected, y_test)
print(Final model score:, final_score)在这个例子中我们创建了一个回归问题的模拟数据集并使用RandomForestRegressor作为评估器。我们初始化了一个空特征集 然后在每次迭代中我们训练模型并基于特征重要性来选择下一个要添加的特征。 我们还设定了停止条件包括最大特征数量和性能提升阈值以确保算法不会无限制地添加特征。 最后我们使用选定的特征集来训练最终的模型并评估其性能。 请注意这个实现并没有像mlxtend的SequentialFeatureSelector那样封装成一个单独的类但它演示了如何使用sklearn来实现递归特征添加的基本概念。
总结
递归特征添加法是一种有效的包裹式特征选择方法它通过逐步向模型中添加特征来优化特征子集。
通过评估每个特征对模型性能的提升递归特征添加法能够构建一个既有效又不过于复杂的特征集。
这种方法不仅考虑了特征的重要性还关注了添加特征后模型性能的提升从而确保了所选特征既能提高预测精度又能避免过度拟合。
然而递归特征添加法也存在一定的计算成本因为它需要在每一步都重新训练模型并评估特征的重要性。
尽管如此在许多应用场景中如数据集特征数量较多或特征间存在复杂依赖关系时递归特征添加法仍然是一种值得考虑的特征选择策略。
通过本文的阐述和代码示例相信读者对递归特征添加法有了更深入的理解并能够在实际项目中灵活运用这一方法。 这篇文章到这里就结束了 谢谢大家的阅读 如果觉得这篇博客对你有用的话别忘记三连哦。 我是豌豆射手^让我们我们下次再见