堆叠泛化是机器学习 (ML) 工程师广泛使用的技术,通过组合多个模型来提高整体预测性能。另一方面,超参数优化 (HPO) 涉及系统搜索最佳超参数集,以更大限度地提高给定 ML 算法的性能。
同时使用堆栈和 HPO 时,一个常见的挑战是巨大的计算需求。这些方法通常需要训练多个模型,并针对每个模型迭代大量超参数组合。这可能会很快变得耗费大量资源和时间,尤其是对于大型数据集而言。
在本文中,我们将演示如何简化此工作流,该工作流将堆栈泛化与 HPO 相结合。我们将展示如何使用 cuML 库的 GPU 加速计算在短短 15 分钟内执行此工作流。得益于 cuML 与 scikit-learn 的零代码更改集成,您可以使用现有的 ML 工作流进行 GPU 加速 (无需修改代码) ,并实现相同的模型准确性。与基于 CPU 的执行 (通常一次只运行一个试验) 不同,GPU 加速支持并行执行多个 HPO 试验,显著缩短训练时间。
我们首先讨论我们使用的堆叠方法、其实现以及准确性的提高。然后,我们将讨论 HPO 如何通过搜索最佳 hyperparameters 来提高整体准确性。
堆叠泛化
堆叠泛化是一种成熟的技术,已在实验中得到广泛应用,包括许多 Kaggle 比赛。它是一种有效的集成方法,但由于其计算成本,在实际应用中通常未得到充分利用。
图 1 展示了我们实现的堆栈架构。在基本层面,我们使用了三个不同的模型:Random Forest、K-Nearest Neighbors (KNN) 和 Logistic Regression。然后,将这些基础模型的预测传递给 KNN 元模型,由其根据组合输出进行最终分类。
在实验中,我们使用了分类数据集,其中包含从 源数据集 推断出的 1M 个样本和九个特征。这种设置使我们能够利用每个基础模型的优势,并通过堆叠提高整体预测准确性。

要在现有的 scikit-learn 工作流程中启用 GPU 加速,您只需使用 cuML 库即可。安装完成后,只需添加 magic 命令:
%load_ext cuml.accel
此命令可在底层激活 GPU 加速,无需更改模型创建、训练或评估代码。您可以继续使用熟悉的 scikit-learn 语法,但使用 GPU 加速的 cuML 库实现执行提升。以下代码片段展示了我们如何使用随机森林、KNN 和逻辑回归作为基础模型,并以 KNN 模型作为元学习器来设置堆栈管道。如需亲自试用,请查看 随附的 Jupyter Notebook 。
%load_ext cuml.accel
# Load the cuML libraries
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
# Define base models (level-0 models)
base_models = [
("logistic_regression", LogisticRegression(**lr_study.best_params, max_iter = 20000, tol=1e-3)),
("random_forest", RandomForestClassifier(**rf_study.best_params, random_state = 42)),
("k_nearest_neighbors", KNeighborsClassifier(**knn_study.best_params))
]
# Function to generate meta features for stacking
def generate_meta_features_for_stacking(base_models, X, y, X_meta):
kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
meta_features = cp.zeros((X_meta.shape[0], len(base_models)))
for i, (name, model) in enumerate(base_models):
# Initialize array to hold out-of-fold predictions (for training data only)
meta_predictions = cp.zeros((X.shape[0],))
print("Model name: ", name)
# Out-of-fold predictions (only used if X_meta == X)
for train_idx, val_idx in kfold.split(X, y):
model.fit(cp.array(X.iloc[train_idx]), cp.array(y.iloc[train_idx]))
predictions = model.predict(cp.array(X.iloc[val_idx]))
meta_predictions[val_idx] = predictions.ravel()
# Refit model on full training data for final prediction on X_meta
model.fit(cp.array(X), cp.array(y))
# Predict meta features for test data
predictions = model.predict(cp.array(X_meta))
meta_features[:, i] = cp.array(predictions).ravel()
return meta_features
# meta_train uses out-of-fold predictions to prevent leakage
meta_train = generate_meta_features_for_stacking(base_models, X_train_scaled, y_train_df, X_train_scaled)
# meta_valid uses predictions from base models trained on full training set
meta_valid = generate_meta_features_for_stacking(base_models, X_train_scaled, y_train_df, X_valid_scaled)
如图 2 所示,使用 5-fold stratified cross-validation 测量时,堆叠泛化使预测准确率整体提高了 0.28%。

超参数优化
为了进一步提高堆叠集成的性能,我们将 HPO 应用于每个基础模型和元模型。为便于执行,我们选择了性能最佳的基础模型来生成折叠外预测,并对这些模型进行堆叠以创建新的元数据集。此数据集用于在 KNN 元模型上运行 HPO,进一步优化其性能。
对于 HPO,我们使用 Optuna 库 ,优化分类准确性作为指标。需要注意的是,通过使用 %load_ext cuml.accel 启用 cuML 内核,整个 HPO 过程都得到了 GPU 加速。因此,其语法与 scikit-learn 保持不变。
以下代码段展示了如何为逻辑回归执行 HPO。该方法同样适用于随机森林、KNN 和 KNN 元模型。如需了解完整实现,请查看 随附的 Jupyter Notebook 。
%load_ext cuml.accel
# Load the cuML libraries
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
# Define the model training and evaluation function
def train_and_eval(C=1, penalty='l2'):
lr = LogisticRegression(C = C, penalty = penalty, max_iter = 20000, tol=1e-3)
lr.fit(X_train_scaled, y_train_df)
y_proba = lr.predict_proba(X_valid_scaled)[:, 1]
# Compute accuracy score
score = cp.round(lr.score(cp.asnumpy(X_valid_scaled), cp.asnumpy(y_valid_df)) * 100, 2)
return score
# Define the Optuna objective function for hyperparameter tuning
def objective(trial):
C = trial.suggest_float("C", 1e-2, 1e2, log = True)
penalty = trial.suggest_categorical("penalty", ["l1", "l2"])
return train_and_eval(C, penalty)
# Create an Optuna study to maximize accuracy score
lr_study = optuna.create_study(
direction="maximize",
study_name="optuna_logistic_acc_score",
sampler=optuna.samplers.RandomSampler(seed=142),
)
# Launch hyperparameter optimization with the defined objective
lr_study.optimize(objective, n_trials=40)
# Print the best hyperparameter set and its corresponding evaluation score
print(f"Best params: {lr_study.best_params}")
print(f"Best accuracy score: {lr_study.best_value}")
如图 3 所示,与不使用 HPO 的模型相比,在基础模型和元模型上应用 HPO 后,预测准确率提高了 1.44%。

将 GPU 加速与 cuML 结合使用的优势
为了提高执行速度,尤其是在四个不同模型的 HPO 期间,利用 GPU 加速的 cuML 库非常有用。它支持在基于 CPU 的执行仅需一次迭代所需的相同时间范围内完成多次迭代。
在我们的场景中,我们设法为每个模型进行了大约 40 次迭代,每次迭代大约需要 5 秒,而在 CPU 上,模型的一次迭代通常大约需要 5 分钟。此外,激活 GPU 加速非常简单,只需在代码中包含 the %load_ext cuml.accel
命令,即可与 scikit-learn 无缝集成。
开始使用
通过将堆叠泛化与 HPO 集成,可以提高系统的准确性。我们提出的解决方案使用 GPU 加速的 cuML 库,使数据科学家能够为堆栈泛化堆栈中的每个模型执行深度 HPO。cuML 库与 scikit-learn 语法的兼容性使开发者能够将此技术无缝整合到生产环境中。该集成不仅有助于开发出色的模型,还加速了迭代过程,从而使数据科学家和开发者能够在现实世界的应用中实现更快的执行并提高模型性能。
要在您自己的应用中试用此方法,请下载最新版本的 NVIDIA cuML 。您可以随时在 Slack 上分享您的反馈,网址是 #RAPIDS-GoAi 。
如需详细了解 零代码更改 cuML ,请参阅 NVIDIA cuML 为 scikit-learn 带来零代码更改加速 。有关此功能的更多示例,请参阅 Google Colab 笔记本 。最新版本的 cuML 具有零代码更改功能,已预安装在 Google Colab 中。有关自定进度课程和讲师指导课程,请参阅 适用于数据科学的 DLI 学习路径 。