提升机器学习模型性能 (续)
提高机器学习模型性能
Section titled “提高机器学习模型性能”构建初始的机器学习模型仅仅是第一步。要达到最优性能,通常需要迭代地进行改进。这包括各种策略,例如数据预处理、特征工程、算法选择以及超参数调优 (hyperparameter tuning)(也称为算法调优)。
通过超参数调优提升性能
Section titled “通过超参数调优提升性能”大多数机器学习算法都有一些设置,称为超参数 (hyperparameters),这些参数不是从数据中学习得到的,而是在训练过程开始之前设置的。这些超参数控制着学习过程本身的各个方面,例如模型的复杂度或正则化强度。
例子包括:
- 支持向量机 (SVM) 中的
C参数。 - K 近邻 (KNN) 中的
k。 - 岭回归 (Ridge) 或 Lasso 回归中的
alpha正则化参数。 - 随机森林 (Random Forests) 中的树的数量 (
n_estimators) 或最大深度 (max_depth)。
相比之下,参数 (parameters)(例如线性回归中的系数或神经网络中的权重)是在训练过程中从数据中学习得到的。
**超参数调优(或优化)**是系统性地搜索超参数值组合的过程,以找到在给定问题和数据集上能够产生最佳模型性能(在验证集上或通过交叉验证评估)的组合。
Scikit-learn 为此提供了出色的工具,主要是网格搜索 (Grid Search) 和随机搜索 (Randomized Search)。
网格搜索 (GridSearchCV)
Section titled “网格搜索 (GridSearchCV)”网格搜索对超参数空间的指定子集执行穷举搜索。你定义一个想要尝试的超参数值“网格”,然后 GridSearchCV 会使用交叉验证对所有可能的组合进行模型训练和评估。
优点: 保证找到指定网格内的最佳组合。
缺点: 计算成本可能非常高,特别是当网格很大或涉及很多超参数时(“维度诅咒”)。
示例:对岭回归的 alpha 进行调优
Section titled “示例:对岭回归的 alpha 进行调优”我们将在 Diabetes 数据集上对岭回归 (Ridge Regression) 的正则化强度 (alpha) 进行调优。
import numpy as npfrom sklearn.datasets import load_diabetesfrom sklearn.linear_model import Ridgefrom sklearn.model_selection import GridSearchCVfrom sklearn.preprocessing import StandardScalerfrom sklearn.pipeline import Pipeline
# 加载 diabetes 数据集diabetes = load_diabetes()X, y = diabetes.data, diabetes.target
# 使用正则化时,对数据进行缩放至关重要# 我们使用 Pipeline 将缩放和模型组合在一起pipe = Pipeline([ ('scaler', StandardScaler()), ('ridge', Ridge())])
# 定义要搜索的 alpha 值网格# 对于正则化参数,使用对数范围很常见alphas = np.logspace(-4, 2, 7) # 示例:从 0.0001 到 100 的 7 个值param_grid = {'ridge__alpha': alphas} # 注意管道步骤使用 '__' 表示法
# 设置 GridSearchCV# cv=5 表示 5 折交叉验证# scoring='neg_mean_squared_error' - GridSearchCV 最大化分数,所以使用负 MSE 进行最小化grid_search = GridSearchCV(estimator=pipe, param_grid=param_grid, cv=5, scoring='neg_mean_squared_error', verbose=1) # verbose 显示进度
# 将网格搜索拟合到数据上grid_search.fit(X, y)
# 打印最佳分数 (平均 CV 分数) 和最佳参数print(f"Best Cross-Validation Score (Negative MSE): {grid_search.best_score_:.4f}")print(f"Best Parameters found: {grid_search.best_params_}")
# 访问最佳估计器 (带有最佳 alpha 的 pipeline)best_model = grid_search.best_estimator_print(f"\nBest Ridge alpha: {best_model.named_steps['ridge'].alpha}")输出 (示例)
Section titled “输出 (示例)”Fitting 5 folds for each of 7 candidates, totalling 35 fits...Best Cross-Validation Score (Negative MSE): -2921.4895Best Parameters found: {'ridge__alpha': 1.0}
Best Ridge alpha: 1.0输出显示了在交叉验证期间获得的最佳负 MSE 分数以及产生此分数的相应 alpha 值(在此示例运行中为 1.0)。使用 Pipeline 确保在每个交叉验证折叠中正确执行了数据缩放。
随机搜索 (RandomizedSearchCV)
Section titled “随机搜索 (RandomizedSearchCV)”随机搜索从指定的统计分布(或列表中)随机抽取固定数量 (n_iter) 的超参数组合。它不会尝试所有组合,而是探索参数空间的随机子集。
优点: 计算效率比网格搜索高得多,尤其是在超参数很多的情况下。通常能更快地找到非常好的(即使不是绝对最优的)超参数。
缺点: 不保证找到最优组合;结果取决于迭代次数和随机采样。
示例:对岭回归的 alpha 进行调优
Section titled “示例:对岭回归的 alpha 进行调优”我们将使用随机搜索更有效地探索更广泛的 alpha 值范围。
import numpy as npfrom sklearn.datasets import load_diabetesfrom sklearn.linear_model import Ridgefrom sklearn.model_selection import RandomizedSearchCVfrom sklearn.preprocessing import StandardScalerfrom sklearn.pipeline import Pipelinefrom scipy.stats import uniform # 用于从均匀分布中采样
# 加载 diabetes 数据集diabetes = load_diabetes()X, y = diabetes.data, diabetes.target
# 设置 pipelinepipe = Pipeline([ ('scaler', StandardScaler()), ('ridge', Ridge())])
# 定义要采样的参数分布# 从 0 到 10 的均匀分布中采样 alphaparam_distributions = { 'ridge__alpha': uniform(loc=0, scale=10) # 从 U(0, 10) 中采样}
# 设置 RandomizedSearchCV# n_iter 控制采样多少个参数设置# random_state 确保结果可复现random_search = RandomizedSearchCV(estimator=pipe, param_distributions=param_distributions, n_iter=50, # 尝试 50 种随机组合 cv=5, scoring='neg_mean_squared_error', random_state=42, verbose=1)
# 将随机搜索拟合到数据上random_search.fit(X, y)
# 打印最佳分数和最佳参数print(f"Best Cross-Validation Score (Negative MSE): {random_search.best_score_:.4f}")print(f"Best Parameters found: {random_search.best_params_}")
# 访问最佳估计器best_model = random_search.best_estimator_print(f"\nBest Ridge alpha: {best_model.named_steps['ridge'].alpha:.4f}")输出 (示例)
Section titled “输出 (示例)”Fitting 5 folds for each of 50 candidates, totalling 250 fits...Best Cross-Validation Score (Negative MSE): -2921.4214Best Parameters found: {'ridge__alpha': 0.9370821941623886}
Best Ridge alpha: 0.9371随机搜索探索了从均匀分布中采样的 50 个不同的 alpha 值。最佳分数与网格搜索找到的非常接近,但如果在网格搜索空间大得多时,计算量可能更少。找到的最佳 alpha 大约为 0.937。
其他性能改进策略
Section titled “其他性能改进策略”除了超参数调优,还可以考虑以下策略:
- 特征工程 (Feature Engineering): 从现有特征创建新特征,选择相关特征,或移除不相关/冗余的特征。
- 数据增强/收集 (Data Augmentation/Collection): 获取更多相关的训练数据。
- 处理缺失数据 (Handling Missing Data): 使用适当的插补技术。
- 处理类别不平衡 (Addressing Class Imbalance): 使用 SMOTE、ADASYN 等技术或调整类别权重。
- 算法选择 (Algorithm Selection): 尝试不同类型的算法,它们可能更适合数据的结构。
- 集成方法 (Ensemble Methods): 组合多个模型(例如 Bagging, Boosting, Stacking)通常能带来比单一模型更好的性能和鲁棒性。
高级调优技术
Section titled “高级调优技术”对于复杂的搜索空间或计算成本高昂的模型,存在更高级的技术:
- 贝叶斯优化 (Bayesian Optimization): 使用概率模型引导搜索,以更有前景的超参数区域为目标(例如,使用
scikit-optimize或Hyperopt等库)。 - 逐次减半 / HyperBand (Successive Halving / HyperBand): 迭代地将资源分配给有前景的配置,快速淘汰效果差的配置(例如,较新版本 scikit-learn 中的
HalvingGridSearchCV,HalvingRandomSearchCV)。
- Scikit-learn 调优文档: https://scikit-learn.org/stable/modules/grid_search.html
- Scikit-learn Pipeline 文档: https://scikit-learn.org/stable/modules/compose.html#pipeline