StackingCVRegressor:带交叉验证的回归堆叠

用于堆叠回归的集成学习元回归器

from mlxtend.regressor import StackingCVRegressor

概述

堆叠是一种集成学习技术,通过元回归器组合多个回归模型。StackingCVRegressor 使用折外预测扩展了标准堆叠算法(实现为 StackingRegressor),以准备用于二级回归器的输入数据。

在标准堆叠过程中,第一级回归器使用与用于准备二级回归器输入数据相同的训练集进行拟合,这可能导致过拟合。然而,StackingCVRegressor 使用了折外预测的概念:数据集被分成 k 折,在连续的 k 轮中,使用 k-1 折来拟合第一级回归器。在每一轮中,然后将第一级回归器应用于每次迭代中未用于模型拟合的剩余 1 折子集。然后将产生的预测结果堆叠起来,作为输入数据提供给二级回归器。在 StackingCVRegressor 训练完成后,第一级回归器会使用整个数据集进行拟合,以获得最优预测结果。

参考文献

示例 1:波士顿住房数据预测

在此示例中,我们在波士顿住房数据集上评估了一些基本预测模型,并查看结合 StackingCVRegressor 组合模型如何影响 MSE 分数。下面的代码输出表明堆叠模型在该数据集上表现最佳——略优于最佳单一回归模型。

from mlxtend.regressor import StackingCVRegressor
from sklearn.datasets import load_boston
from sklearn.svm import SVR
from sklearn.linear_model import Lasso
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import cross_val_score
import numpy as np

RANDOM_SEED = 42

X, y = load_boston(return_X_y=True)

svr = SVR(kernel='linear')
lasso = Lasso()
rf = RandomForestRegressor(n_estimators=5, 
                           random_state=RANDOM_SEED)

# Starting from v0.16.0, StackingCVRegressor supports
# `random_state` to get deterministic result.
stack = StackingCVRegressor(regressors=(svr, lasso, rf),
                            meta_regressor=lasso,
                            random_state=RANDOM_SEED)

print('5-fold cross validation scores:\n')

for clf, label in zip([svr, lasso, rf, stack], ['SVM', 'Lasso', 
                                                'Random Forest', 
                                                'StackingCVRegressor']):
    scores = cross_val_score(clf, X, y, cv=5)
    print("R^2 Score: %0.2f (+/- %0.2f) [%s]" % (
        scores.mean(), scores.std(), label))
5-fold cross validation scores:

R^2 Score: 0.46 (+/- 0.29) [SVM]
R^2 Score: 0.43 (+/- 0.14) [Lasso]
R^2 Score: 0.53 (+/- 0.28) [Random Forest]
R^2 Score: 0.57 (+/- 0.24) [StackingCVRegressor]
stack = StackingCVRegressor(regressors=(svr, lasso, rf),
                            meta_regressor=lasso)

print('5-fold cross validation scores:\n')

for clf, label in zip([svr, lasso, rf, stack], ['SVM', 'Lasso', 
                                                'Random Forest', 
                                                'StackingCVRegressor']):
    scores = cross_val_score(clf, X, y, cv=5, scoring='neg_mean_squared_error')
    print("Neg. MSE Score: %0.2f (+/- %0.2f) [%s]" % (
        scores.mean(), scores.std(), label))
5-fold cross validation scores:

Neg. MSE Score: -33.33 (+/- 22.36) [SVM]
Neg. MSE Score: -35.53 (+/- 16.99) [Lasso]
Neg. MSE Score: -27.08 (+/- 15.67) [Random Forest]
Neg. MSE Score: -25.85 (+/- 17.22) [StackingCVRegressor]

示例 2:结合 GridSearchCV 进行堆叠

在第二个示例中,我们演示了 StackingCVRegressor 如何与 GridSearchCV 结合使用。堆叠仍然允许调整基础模型和元模型的超参数!

例如,我们可以使用 estimator.get_params().keys() 获取可调参数的完整列表。

from mlxtend.regressor import StackingCVRegressor
from sklearn.datasets import load_boston
from sklearn.linear_model import Lasso
from sklearn.linear_model import Ridge
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import GridSearchCV

X, y = load_boston(return_X_y=True)

ridge = Ridge(random_state=RANDOM_SEED)
lasso = Lasso(random_state=RANDOM_SEED)
rf = RandomForestRegressor(random_state=RANDOM_SEED)

stack = StackingCVRegressor(regressors=(lasso, ridge),
                            meta_regressor=rf, 
                            random_state=RANDOM_SEED,
                            use_features_in_secondary=True)

params = {'lasso__alpha': [0.1, 1.0, 10.0],
          'ridge__alpha': [0.1, 1.0, 10.0]}

grid = GridSearchCV(
    estimator=stack, 
    param_grid={
        'lasso__alpha': [x/5.0 for x in range(1, 10)],
        'ridge__alpha': [x/20.0 for x in range(1, 10)],
        'meta_regressor__n_estimators': [10, 100]
    }, 
    cv=5,
    refit=True
)

grid.fit(X, y)

print("Best: %f using %s" % (grid.best_score_, grid.best_params_))
Best: 0.679151 using {'lasso__alpha': 1.6, 'meta_regressor__n_estimators': 10, 'ridge__alpha': 0.4}
cv_keys = ('mean_test_score', 'std_test_score', 'params')

for r, _ in enumerate(grid.cv_results_['mean_test_score']):
    print("%0.3f +/- %0.2f %r"
          % (grid.cv_results_[cv_keys[0]][r],
             grid.cv_results_[cv_keys[1]][r] / 2.0,
             grid.cv_results_[cv_keys[2]][r]))
    if r > 10:
        break
print('...')

print('Best parameters: %s' % grid.best_params_)
print('Accuracy: %.2f' % grid.best_score_)
0.632 +/- 0.09 {'lasso__alpha': 0.2, 'meta_regressor__n_estimators': 10, 'ridge__alpha': 0.05}
0.645 +/- 0.08 {'lasso__alpha': 0.2, 'meta_regressor__n_estimators': 10, 'ridge__alpha': 0.1}
0.641 +/- 0.08 {'lasso__alpha': 0.2, 'meta_regressor__n_estimators': 10, 'ridge__alpha': 0.15}
0.653 +/- 0.08 {'lasso__alpha': 0.2, 'meta_regressor__n_estimators': 10, 'ridge__alpha': 0.2}
0.622 +/- 0.10 {'lasso__alpha': 0.2, 'meta_regressor__n_estimators': 10, 'ridge__alpha': 0.25}
0.630 +/- 0.09 {'lasso__alpha': 0.2, 'meta_regressor__n_estimators': 10, 'ridge__alpha': 0.3}
0.630 +/- 0.09 {'lasso__alpha': 0.2, 'meta_regressor__n_estimators': 10, 'ridge__alpha': 0.35}
0.642 +/- 0.09 {'lasso__alpha': 0.2, 'meta_regressor__n_estimators': 10, 'ridge__alpha': 0.4}
0.654 +/- 0.08 {'lasso__alpha': 0.2, 'meta_regressor__n_estimators': 10, 'ridge__alpha': 0.45}
0.642 +/- 0.09 {'lasso__alpha': 0.2, 'meta_regressor__n_estimators': 100, 'ridge__alpha': 0.05}
0.645 +/- 0.09 {'lasso__alpha': 0.2, 'meta_regressor__n_estimators': 100, 'ridge__alpha': 0.1}
0.648 +/- 0.09 {'lasso__alpha': 0.2, 'meta_regressor__n_estimators': 100, 'ridge__alpha': 0.15}
...
Best parameters: {'lasso__alpha': 1.6, 'meta_regressor__n_estimators': 10, 'ridge__alpha': 0.4}
Accuracy: 0.68

注意

StackingCVRegressor 还支持对 regressors 进行网格搜索,甚至对单个基础回归器也可以。当存在层级混合的超参数时,GridSearchCV 将尝试按自上而下的顺序替换超参数,即 regressors -> 单个基础回归器 -> 回归器超参数。例如,给定如下超参数网格:

params = {'randomforestregressor__n_estimators': [1, 100],
'regressors': [(regr1, regr1, regr1), (regr2, regr3)]}

它将首先使用 (regr1, regr2, regr3)(regr2, regr3) 的实例设置。然后,它将根据 'randomforestregressor__n_estimators': [1, 100] 替换匹配回归器的 'n_estimators' 设置。

API

StackingCVRegressor(regressors, meta_regressor, cv=5, shuffle=True, random_state=None, verbose=0, refit=True, use_features_in_secondary=False, store_train_meta_features=False, n_jobs=None, pre_dispatch='2*n_jobs', multi_output=False)

一个用于 scikit-learn 估计器的“带交叉验证的堆叠”回归器。

参数

  • regressors : 类似数组, shape = [n_regressors]

    回归器列表。在 StackingCVRegressor 上调用 fit 方法将拟合这些原始回归器的克隆,这些克隆将存储在类属性 self.regr_ 中。

  • meta_regressor : 对象

    用于拟合回归器集合的元回归器

  • cv : 整型, 交叉验证生成器或可迭代对象, 可选 (默认: 5)

    确定交叉验证的分割策略。cv 的可能输入包括: - None,使用默认的 5 折交叉验证, - 整型,指定 KFold 中的折数, - 一个用作交叉验证生成器的对象。 - 一个生成训练集和测试集分割的可迭代对象。对于整型/None 输入,将使用 KFold 交叉验证。

  • shuffle : 布尔型 (默认: True)

    如果为 True 且 cv 参数为整型,则在拟合阶段进行交叉验证之前将打乱训练数据。如果 cv 参数是特定的交叉验证技术,则忽略此参数。

  • random_state : 整型, RandomState 实例或 None, 可选 (默认: None)

    控制 cv 分割器的随机性。当 cv 是整型且 shuffle=True 时使用。v0.16.0 新增。

  • verbose : 整型, 可选 (默认=0)

    控制构建过程的详细程度。v0.16.0 新增。

  • refit : 布尔型 (默认: True)

    如果为 True (默认),则克隆用于堆叠回归的回归器;否则使用原始回归器,在调用 fit 方法时将在数据集上重新拟合它们。如果使用的估计器支持 scikit-learn 的 fit/predict API 接口但不兼容 scikit-learn 的 clone 函数,建议设置 refit=False。

  • use_features_in_secondary : 布尔型 (默认: False)

    如果为 True,元回归器将在原始回归器的预测结果和原始数据集上进行训练。如果为 False,元回归器将仅在原始回归器的预测结果上进行训练。

  • store_train_meta_features : 布尔型 (默认: False)

    如果为 True,用于拟合元回归器的训练数据计算出的元特征将存储在 self.train_meta_features_ 数组中,可在调用 fit 后访问。

  • n_jobs : 整型或 None, 可选 (默认: None)

    用于执行计算的 CPU 数量。None 表示 1,除非在 :obj:joblib.parallel_backend 上下文中。-1 表示使用所有处理器。详情请参阅 :term:Glossary 。v0.16.0 新增。

  • pre_dispatch : 整型或字符串, 可选

    控制并行执行期间调度的作业数量。减少此数量有助于避免在调度的作业超出 CPU 处理能力时内存消耗爆炸。此参数可以是: - None,在这种情况下,所有作业都会立即创建和生成。用于轻量级且快速运行的作业,以避免按需生成作业引起的延迟 - 整型,表示要生成的总作业数 - 字符串,表示作为 n_jobs 函数的表达式,例如 '2*n_jobs'

  • multi_output : 布尔型 (默认: False)

    如果为 True,则允许多输出目标,但禁止 nan 或 inf 值。如果为 False,y 将被检查是否为向量。(v0.19.0 新增。)

属性

  • train_meta_features : numpy 数组, shape = [n_samples, n_regressors]

    训练数据的元特征,其中 n_samples 是训练数据中的样本数,len(self.regressors) 是回归器数量。

示例

有关使用示例,请参阅 https://mlxtend.cn/mlxtend/user_guide/regressor/StackingCVRegressor/

方法


fit(X, y, groups=None, sample_weight=None)

拟合集成回归器和元回归器。

参数

  • X : numpy 数组, shape = [n_samples, n_features]

    训练向量,其中 n_samples 是样本数量,n_features 是特征数量。

  • y : numpy 数组, shape = [n_samples] 或 [n_samples, n_targets]

    目标值。仅当 self.multi_output 为 True 时才支持多目标。

  • groups : numpy 数组/None, shape = [n_samples]

    每个样本所属的组。这由特定的交叉验证策略(例如 GroupKFold())使用。

  • sample_weight : 类似数组, shape = [n_samples], 可选

    作为 sample_weights 传递给回归器列表中的每个回归器以及元回归器的样本权重。如果某些回归器的 fit() 方法不支持 sample_weight,则会引发错误。

返回

  • self : 对象

fit_transform(X, y=None, **fit_params)

拟合数据,然后进行转换。

Fits transformer to `X` and `y` with optional parameters `fit_params`
and returns a transformed version of `X`.

参数

  • X : 类似数组, shape (n_samples, n_features)

    输入样本。

  • y : 类似数组, shape (n_samples,) 或 (n_samples, n_outputs), 默认=None

    目标值(对于无监督转换,为 None)。

  • **fit_params : 字典

    附加拟合参数。

返回

  • X_new : ndarray 数组, shape (n_samples, n_features_new)

    转换后的数组。


get_params(deep=True)

获取此估计器的参数。

参数

  • deep : 布尔型, 默认=True

    如果为 True,将返回此估计器及其包含的作为估计器的子对象的参数。

返回

  • params : 字典

    参数名称与其值的映射。


predict(X)

预测 X 的目标值。

参数

  • X : {类似数组, 稀疏矩阵}, shape = [n_samples, n_features]

    训练向量,其中 n_samples 是样本数量,n_features 是特征数量。

返回

  • y_target : 类似数组, shape = [n_samples] 或 [n_samples, n_targets]

    预测的目标值。


predict_meta_features(X)

获取测试数据的元特征。

参数

  • X : numpy 数组, shape = [n_samples, n_features]

    测试向量,其中 n_samples 是样本数量,n_features 是特征数量。

返回

  • meta-features : numpy 数组, shape = [n_samples, len(self.regressors)]

    测试数据的元特征,其中 n_samples 是测试数据中的样本数,len(self.regressors) 是回归器数量。如果 self.multi_output 为 True,则列数是 len(self.regressors) * n_targets。


score(X, y, sample_weight=None)

返回预测的决定系数 :math:R^2

The coefficient :math:`R^2` is defined as :math:`(1 - \frac{u}{v})`,
where :math:`u` is the residual sum of squares ``((y_true - y_pred)

** 2).sum(),:math:`v` 是总平方和((y_true - y_true.mean()) ** 2).sum()``。最优分数是 1.0,并且它

可以为负(因为模型可能任意差)。一个

忽略输入特征,总是预测 y 的期望值的常数模型,将获得 0.0 的 :math:R^2 分数。

参数

  • X : 类似数组, shape (n_samples, n_features)

    测试样本。对于某些估计器,这可能是一个预计算的核矩阵或通用对象列表,其形状为 (n_samples, n_samples_fitted),其中 n_samples_fitted 是用于估计器拟合的样本数量。

  • y : 类似数组, shape (n_samples,) 或 (n_samples, n_outputs)

    X 的真实值。

  • sample_weight : 类似数组, shape (n_samples,), 默认=None

    样本权重。

返回

  • score : 浮点型

    关于 yself.predict(X) 的 :math:R^2

注意

在回归器上调用 score 时使用的 :math:R^2 分数从版本 0.23 开始使用 multioutput='uniform_average',以与 :func:~sklearn.metrics.r2_score 的默认值保持一致。这会影响所有多输出回归器(除了 :class:~sklearn.multioutput.MultiOutputRegressor)的 score 方法。


set_params(**params)

设置此估计器的参数。

Valid parameter keys can be listed with ``get_params()``.

返回

self

属性


named_regressors

返回

命名估计器元组列表,例如 [('svc', SVC(...))]