Machine Learning Mastery 集成学习教程(七)
使用 Python 开发堆叠集成机器学习
最后更新于 2021 年 4 月 27 日
堆叠或堆叠泛化是一种集成机器学习算法。
它使用元学习算法来学习如何最好地组合来自两个或多个基本机器学习算法的预测。
堆叠的好处是,它可以利用一系列在分类或回归任务中表现良好的模型的能力,并做出比集成中的任何单个模型表现更好的预测。
在本教程中,您将发现 Python 中的堆叠泛化集成或堆叠。
完成本教程后,您将知道:
- 堆叠是一种集成机器学习算法,它学习如何最好地组合来自多个表现良好的机器学习模型的预测。
- Sklearn 库提供了 Python 中堆叠集成的标准实现。
- 如何使用堆叠集成进行回归和分类预测建模?
用我的新书Python 集成学习算法启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
- 2020 年 8 月更新:改进代码示例,增加更多参考。
用 Python 堆叠集成机器学习 图片由lamix提供,保留部分权利。
教程概述
本教程分为四个部分;它们是:
- 堆叠一般化
- 堆叠科学工具包-学习应用编程接口
- 分类堆叠
- 回归的叠加
堆叠一般化
堆叠泛化或简称“T0”堆叠是一种集成机器学习算法。
它包括在同一数据集上组合来自多个机器学习模型的预测,如装袋和提升。
堆叠解决了这个问题:
- 给定多个在一个问题上很熟练的机器学习模型,但是以不同的方式,你如何选择使用哪个模型(信任)?
解决这个问题的方法是使用另一个机器学习模型,该模型学习何时使用或信任集成中的每个模型。
- 与装袋不同,在堆叠中,模型通常是不同的(例如,不是所有的决策树),并且适合同一数据集(例如,代替训练数据集的样本)。
- 与增强不同,在堆叠中,使用单个模型来学习如何最好地组合来自贡献模型的预测(例如,代替校正先前模型的预测的模型序列)。
堆叠模型的体系结构包括两个或多个基础模型,通常称为 0 级模型,以及一个组合基础模型预测的元模型,称为 1 级模型。
- 0 级模型(基础模型 ) :模型适合训练数据,并且其预测被编译。
- 一级模型(元模型 ) :学习如何最好地组合基础模型预测的模型。
元模型基于基础模型对样本外数据的预测进行训练。也就是说,不用于训练基本模型的数据被馈送到基本模型,进行预测,并且这些预测连同预期输出一起提供用于拟合元模型的训练数据集的输入和输出对。
用作元模型输入的基本模型的输出在回归的情况下可以是真实值,在分类的情况下可以是概率值、类概率值或类标签。
为元模型准备训练数据集的最常见方法是通过基础模型的 k 倍交叉验证,其中超倍预测被用作元模型的训练数据集的基础。
元模型的训练数据还可以包括基础模型的输入,例如训练数据的输入元素。这可以为元模型提供关于如何最好地组合来自元模型的预测的附加上下文。
一旦为元模型准备了训练数据集,就可以在这个数据集上独立地训练元模型,并且可以在整个原始训练数据集上训练基本模型。
当多个不同的机器学习模型在一个数据集上有技能,但在不同的方面有技能时,堆叠是合适的。另一种说法是,模型做出的预测或模型做出的预测中的误差是不相关的或具有低相关性。
基础模型通常复杂多样。因此,使用一系列对如何解决预测建模任务做出非常不同假设的模型通常是一个好主意,例如线性模型、决策树、支持向量机、神经网络等。其他集成算法也可以用作基础模型,例如随机森林。
- 基础模型:使用不同范围的模型,对预测任务做出不同的假设。
元模型通常很简单,提供了对基础模型所做预测的平滑解释。因此,线性模型通常用作元模型,例如回归任务的线性回归(预测数值)和分类任务的逻辑回归(预测类别标签)。虽然这很常见,但不是必需的。
- 回归元模型:线性回归。
- 分类元模型:逻辑回归。
使用一个简单的线性模型作为元模型通常会给出堆叠的通俗名称“混合”与预测一样,是基本模型所做预测的加权平均或混合。
超级学习器可以被认为是一种特殊类型的堆叠。
堆叠旨在提高建模表现,尽管不能保证在所有情况下都能带来改进。
实现表现的提高取决于问题的复杂性,以及它是否足够好地由训练数据表示,并且足够复杂,以至于可以通过组合预测来学习更多。这也取决于基础模型的选择,以及它们在预测(或误差)方面是否足够熟练和足够不相关。
如果基础模型的表现与堆叠集成一样好或更好,则应该使用基础模型,因为它的复杂性更低(例如,描述、训练和维护更简单)。
堆叠科学工具包-学习应用编程接口
堆叠可以从零开始实现,尽管这对初学者来说很有挑战性。
有关在 Python 中从零开始实现堆栈的示例,请参见教程:
有关为深度学习从零开始实现堆叠的示例,请参见教程:
Sklearn Python 机器学习库为机器学习提供了堆栈的实现。
它在 0.22 版及更高版本的库中可用。
首先,通过运行以下脚本来确认您使用的是现代版本的库:
# check Sklearn version
import sklearn
print(sklearn.__version__)
运行脚本将打印您的 Sklearn 版本。
您的版本应该相同或更高。如果没有,您必须升级 Sklearn 库的版本。
0.22.1
两个模型的操作方式相同,采用的参数也相同。使用模型需要指定一个估计量列表(0 级模型)和一个最终估计量(1 级或元模型)。
0 级模型或基础模型的列表通过“估计器参数提供。这是一个 Python 列表,其中列表中的每个元素都是一个元组,具有模型的名称和配置的模型实例。
例如,下面定义了两个 0 级模型:
...
models = [('lr',LogisticRegression()),('svm',SVC())
stacking = StackingClassifier(estimators=models)
列表中的每个模型也可以是管道,包括模型在训练数据集中拟合模型之前所需的任何数据准备。例如:
...
models = [('lr',LogisticRegression()),('svm',make_pipeline(StandardScaler(),SVC()))
stacking = StackingClassifier(estimators=models)
一级模型或元模型通过“ final_estimator ”参数提供。默认情况下,回归设置为线性回归,分类设置为后勤回归,这些都是您可能不想更改的合理默认值。
元模型的数据集是使用交叉验证准备的。默认情况下,使用 5 倍交叉验证,尽管这可以通过“ cv ”参数进行更改,并设置为数字(例如,10 倍交叉验证为 10)或交叉验证对象(例如,stratifiedfold)。
有时,如果为元模型准备的数据集也包括 0 级模型的输入,例如输入训练数据,则可以获得更好的表现。这可以通过将“通过”参数设置为真来实现,默认情况下不启用。
现在我们已经熟悉了 Sklearn 中的堆栈 API,让我们来看看一些工作示例。
分类堆叠
在这一节中,我们将研究使用堆叠来解决分类问题。
首先,我们可以使用 make_classification()函数创建一个包含 1000 个示例和 20 个输入特征的合成二进制分类问题。
下面列出了完整的示例。
# test classification dataset
from sklearn.datasets import make_classification
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# summarize the dataset
print(X.shape, y.shape)
运行该示例将创建数据集并总结输入和输出组件的形状。
(1000, 20) (1000,)
接下来,我们可以在数据集上评估一套不同的机器学习模型。
具体来说,我们将评估以下五种算法:
- 逻辑回归。
- k-最近邻居。
- 决策树。
- 支持向量机。
- 朴素贝叶斯。
将使用默认模型超参数评估每个算法。下面的函数 get_models() 创建我们想要评估的模型。
# get a list of models to evaluate
def get_models():
models = dict()
models['lr'] = LogisticRegression()
models['knn'] = KNeighborsClassifier()
models['cart'] = DecisionTreeClassifier()
models['svm'] = SVC()
models['bayes'] = GaussianNB()
return models
每个模型将使用重复的 k 倍交叉验证进行评估。
下面的 evaluate_model() 函数获取一个模型实例,并从三次重复的分层 10 倍交叉验证中返回一个分数列表。
# evaluate a given model using cross-validation
def evaluate_model(model, X, y):
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
return scores
然后,我们可以报告每种算法的平均表现,并创建一个方框图和触须图来比较每种算法的准确性分数分布。
将这些联系在一起,完整的示例如下所示。
# compare standalone models for binary classification
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
models['lr'] = LogisticRegression()
models['knn'] = KNeighborsClassifier()
models['cart'] = DecisionTreeClassifier()
models['svm'] = SVC()
models['bayes'] = GaussianNB()
return models
# evaluate a given model using cross-validation
def evaluate_model(model, X, y):
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
scores = evaluate_model(model, X, y)
results.append(scores)
names.append(name)
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行该示例首先报告每个模型的平均值和标准偏差准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
我们可以看到,在这种情况下,SVM 表现最好,平均准确率约为 95.7%。
>lr 0.866 (0.029)
>knn 0.931 (0.025)
>cart 0.821 (0.050)
>svm 0.957 (0.020)
>bayes 0.833 (0.031)
然后创建一个方框图,比较每个模型的分布准确率分数,让我们清楚地看到 KNN 和 SVM 的平均表现优于 LR、CART 和 Bayes。
二分类独立模型准确率的箱线图
这里我们有五种不同的算法表现良好,大概在这个数据集上以不同的方式。
接下来,我们可以尝试使用堆叠将这五个模型组合成单个集成模型。
我们可以使用逻辑回归模型来学习如何最好地组合来自五个独立模型的预测。
下面的 get_stacking() 函数定义了 StackingClassifier 模型,首先定义了五个基本模型的元组列表,然后定义了逻辑回归元模型,使用 5 重交叉验证来组合来自基本模型的预测。
# get a stacking ensemble of models
def get_stacking():
# define the base models
level0 = list()
level0.append(('lr', LogisticRegression()))
level0.append(('knn', KNeighborsClassifier()))
level0.append(('cart', DecisionTreeClassifier()))
level0.append(('svm', SVC()))
level0.append(('bayes', GaussianNB()))
# define meta learner model
level1 = LogisticRegression()
# define the stacking ensemble
model = StackingClassifier(estimators=level0, final_estimator=level1, cv=5)
return model
我们可以在要评估的模型列表中包含堆叠集合,以及独立的模型。
# get a list of models to evaluate
def get_models():
models = dict()
models['lr'] = LogisticRegression()
models['knn'] = KNeighborsClassifier()
models['cart'] = DecisionTreeClassifier()
models['svm'] = SVC()
models['bayes'] = GaussianNB()
models['stacking'] = get_stacking()
return models
我们的期望是堆叠集合将比任何单个基础模型表现得更好。
这并不总是这样,如果不是这样,那么应该使用基础模型而不是集合模型。
下面列出了评估堆叠集合模型和独立模型的完整示例。
# compare ensemble to each baseline classifier
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import StackingClassifier
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
return X, y
# get a stacking ensemble of models
def get_stacking():
# define the base models
level0 = list()
level0.append(('lr', LogisticRegression()))
level0.append(('knn', KNeighborsClassifier()))
level0.append(('cart', DecisionTreeClassifier()))
level0.append(('svm', SVC()))
level0.append(('bayes', GaussianNB()))
# define meta learner model
level1 = LogisticRegression()
# define the stacking ensemble
model = StackingClassifier(estimators=level0, final_estimator=level1, cv=5)
return model
# get a list of models to evaluate
def get_models():
models = dict()
models['lr'] = LogisticRegression()
models['knn'] = KNeighborsClassifier()
models['cart'] = DecisionTreeClassifier()
models['svm'] = SVC()
models['bayes'] = GaussianNB()
models['stacking'] = get_stacking()
return models
# evaluate a give model using cross-validation
def evaluate_model(model, X, y):
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
scores = evaluate_model(model, X, y)
results.append(scores)
names.append(name)
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行示例首先报告每个模型的表现。这包括每个基础模型的表现,然后是堆叠集合。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到叠加集成的平均表现似乎比任何单个模型都好,达到了大约 96.4%的准确率。
>lr 0.866 (0.029)
>knn 0.931 (0.025)
>cart 0.820 (0.044)
>svm 0.957 (0.020)
>bayes 0.833 (0.031)
>stacking 0.964 (0.019)
创建一个显示模型分类准确率分布的方框图。
在这里,我们可以看到叠加模型的平均和中值准确率略高于 SVM 模型。
二分类的独立和堆叠模型准确率的箱线图
如果我们选择一个叠加集合作为我们的最终模型,我们可以像任何其他模型一样,拟合并使用它来对新数据进行预测。
首先对所有可用数据进行叠加集合拟合,然后调用 predict() 函数对新数据进行预测。
下面的示例在我们的二进制类别数据集上演示了这一点。
# make a prediction with a stacking ensemble
from sklearn.datasets import make_classification
from sklearn.ensemble import StackingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# define the base models
level0 = list()
level0.append(('lr', LogisticRegression()))
level0.append(('knn', KNeighborsClassifier()))
level0.append(('cart', DecisionTreeClassifier()))
level0.append(('svm', SVC()))
level0.append(('bayes', GaussianNB()))
# define meta learner model
level1 = LogisticRegression()
# define the stacking ensemble
model = StackingClassifier(estimators=level0, final_estimator=level1, cv=5)
# fit the model on all available data
model.fit(X, y)
# make a prediction for one example
data = [[2.47475454,0.40165523,1.68081787,2.88940715,0.91704519,-3.07950644,4.39961206,0.72464273,-4.86563631,-6.06338084,-1.22209949,-0.4699618,1.01222748,-0.6899355,-0.53000581,6.86966784,-3.27211075,-6.59044146,-2.21290585,-3.139579]]
yhat = model.predict(data)
print('Predicted Class: %d' % (yhat))
运行该示例使堆叠集成模型适合整个数据集,然后用于对新的数据行进行预测,就像我们在应用程序中使用该模型时可能做的那样。
Predicted Class: 0
回归的叠加
在这一节中,我们将研究使用堆叠来解决回归问题。
首先,我们可以使用make _ revolution()函数创建一个包含 1000 个示例和 20 个输入特征的合成回归问题。
下面列出了完整的示例。
# test regression dataset
from sklearn.datasets import make_regression
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=1)
# summarize the dataset
print(X.shape, y.shape)
运行该示例将创建数据集并总结输入和输出组件的形状。
(1000, 20) (1000,)
接下来,我们可以在数据集上评估一套不同的机器学习模型。
具体来说,我们将评估以下三种算法:
- k-最近邻居。
- 决策树。
- 支持向量回归。
注:测试数据集可以使用线性回归模型轻松求解,因为数据集是在封面下使用线性模型创建的。因此,我们将这个模型排除在示例之外,这样我们就可以展示堆叠集成方法的优势。
将使用默认模型超参数评估每个算法。下面的函数 get_models() 创建我们想要评估的模型。
# get a list of models to evaluate
def get_models():
models = dict()
models['knn'] = KNeighborsRegressor()
models['cart'] = DecisionTreeRegressor()
models['svm'] = SVR()
return models
每个模型将使用重复的 k 倍交叉验证进行评估。下面的 evaluate_model() 函数获取一个模型实例,并返回三次重复 10 倍交叉验证的分数列表。
# evaluate a given model using cross-validation
def evaluate_model(model, X, y):
cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)
scores = cross_val_score(model, X, y, scoring='neg_mean_absolute_error', cv=cv, n_jobs=-1, error_score='raise')
return scores
然后,我们可以报告每种算法的平均表现,并创建一个方框图和触须图来比较每种算法的准确性分数分布。
在这种情况下,将使用平均绝对误差(MAE)报告模型表现。Sklearn 库反转该错误的符号,使其最大化,从-无穷大到 0,以获得最佳分数。
将这些联系在一起,完整的示例如下所示。
# compare machine learning models for regression
from numpy import mean
from numpy import std
from sklearn.datasets import make_regression
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedKFold
from sklearn.linear_model import LinearRegression
from sklearn.neighbors import KNeighborsRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.svm import SVR
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=1)
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
models['knn'] = KNeighborsRegressor()
models['cart'] = DecisionTreeRegressor()
models['svm'] = SVR()
return models
# evaluate a given model using cross-validation
def evaluate_model(model, X, y):
cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)
scores = cross_val_score(model, X, y, scoring='neg_mean_absolute_error', cv=cv, n_jobs=-1, error_score='raise')
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
scores = evaluate_model(model, X, y)
results.append(scores)
names.append(name)
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行该示例首先报告每个模型的平均和标准偏差 MAE。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
我们可以看到,在这种情况下,KNN 表现最好,平均负 MAE 约为-100。
>knn -101.019 (7.161)
>cart -148.100 (11.039)
>svm -162.419 (12.565)
然后创建一个方框图,比较每个模型的负 MAE 分数分布。
回归的独立模型负平均绝对误差的箱线图
在这里,我们有三种不同的算法表现良好,大概在这个数据集上以不同的方式。
接下来,我们可以尝试使用堆叠将这三个模型组合成单个集成模型。
我们可以使用线性回归模型来学习如何最好地组合来自三个独立模型的预测。
下面的 get_stacking() 函数定义了stackingreductor模型,首先定义三个基本模型的元组列表,然后定义线性回归元模型,使用 5 重交叉验证来组合来自基本模型的预测。
# get a stacking ensemble of models
def get_stacking():
# define the base models
level0 = list()
level0.append(('knn', KNeighborsRegressor()))
level0.append(('cart', DecisionTreeRegressor()))
level0.append(('svm', SVR()))
# define meta learner model
level1 = LinearRegression()
# define the stacking ensemble
model = StackingRegressor(estimators=level0, final_estimator=level1, cv=5)
return model
我们可以在要评估的模型列表中包含堆叠集合,以及独立的模型。
# get a list of models to evaluate
def get_models():
models = dict()
models['knn'] = KNeighborsRegressor()
models['cart'] = DecisionTreeRegressor()
models['svm'] = SVR()
models['stacking'] = get_stacking()
return models
我们的期望是堆叠集合将比任何单个基础模型表现得更好。
这并不总是这样,如果不是这样,那么应该使用基础模型来支持集成模型。
下面列出了评估堆叠集合模型和独立模型的完整示例。
# compare ensemble to each standalone models for regression
from numpy import mean
from numpy import std
from sklearn.datasets import make_regression
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedKFold
from sklearn.linear_model import LinearRegression
from sklearn.neighbors import KNeighborsRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.svm import SVR
from sklearn.ensemble import StackingRegressor
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=1)
return X, y
# get a stacking ensemble of models
def get_stacking():
# define the base models
level0 = list()
level0.append(('knn', KNeighborsRegressor()))
level0.append(('cart', DecisionTreeRegressor()))
level0.append(('svm', SVR()))
# define meta learner model
level1 = LinearRegression()
# define the stacking ensemble
model = StackingRegressor(estimators=level0, final_estimator=level1, cv=5)
return model
# get a list of models to evaluate
def get_models():
models = dict()
models['knn'] = KNeighborsRegressor()
models['cart'] = DecisionTreeRegressor()
models['svm'] = SVR()
models['stacking'] = get_stacking()
return models
# evaluate a given model using cross-validation
def evaluate_model(model, X, y):
cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)
scores = cross_val_score(model, X, y, scoring='neg_mean_absolute_error', cv=cv, n_jobs=-1, error_score='raise')
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
scores = evaluate_model(model, X, y)
results.append(scores)
names.append(name)
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行示例首先报告每个模型的表现。这包括每个基础模型的表现,然后是堆叠集合。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到叠加集成的平均表现似乎比任何单个模型都好,平均负 MAE 约为-56。
>knn -101.019 (7.161)
>cart -148.017 (10.635)
>svm -162.419 (12.565)
>stacking -56.893 (5.253)
创建一个方框图,显示模型误差分数的分布。在这里,我们可以看到堆叠模型的平均和中间分数比任何单个模型都高。
回归的独立和叠加模型负平均绝对误差的箱线图
如果我们选择一个叠加集合作为我们的最终模型,我们可以像任何其他模型一样,拟合并使用它来对新数据进行预测。
首先对所有可用数据进行叠加集合拟合,然后调用 predict() 函数对新数据进行预测。
下面的例子在我们的回归数据集上演示了这一点。
# make a prediction with a stacking ensemble
from sklearn.datasets import make_regression
from sklearn.linear_model import LinearRegression
from sklearn.neighbors import KNeighborsRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.svm import SVR
from sklearn.ensemble import StackingRegressor
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=1)
# define the base models
level0 = list()
level0.append(('knn', KNeighborsRegressor()))
level0.append(('cart', DecisionTreeRegressor()))
level0.append(('svm', SVR()))
# define meta learner model
level1 = LinearRegression()
# define the stacking ensemble
model = StackingRegressor(estimators=level0, final_estimator=level1, cv=5)
# fit the model on all available data
model.fit(X, y)
# make a prediction for one example
data = [[0.59332206,-0.56637507,1.34808718,-0.57054047,-0.72480487,1.05648449,0.77744852,0.07361796,0.88398267,2.02843157,1.01902732,0.11227799,0.94218853,0.26741783,0.91458143,-0.72759572,1.08842814,-0.61450942,-0.69387293,1.69169009]]
yhat = model.predict(data)
print('Predicted Value: %.3f' % (yhat))
运行该示例使堆叠集成模型适合整个数据集,然后用于对新的数据行进行预测,就像我们在应用程序中使用该模型时可能做的那样。
Predicted Value: 556.264
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
相关教程
- 如何用 Python 从零开始实现堆叠泛化(堆叠)
- 如何用 Keras 开发 Python 深度学习神经网络的堆叠集成
- 如何在 Python 中开发超级学习器集成
- 如何在机器学习中使用折外预测
- k 倍交叉验证的温和介绍
报纸
- 堆叠概括,1992。
- 堆叠概括:什么时候起作用?,1997 年。
- 堆叠概括中的问题,1999。
书
- 数据挖掘:实用机器学习工具与技术,2016。
- 统计学习的要素,2017。
- 机器学习:概率视角,2012。
蜜蜂
- 硬化。一起。StackingClassifier API 。
- 硬化。一起。stack ingresor API。
- sklearn . datasets . make _ classification API。
- sklearn . datasets . make _ revolution API。
文章
- 一起学习,维基百科。
摘要
在本教程中,您发现了 Python 中的堆叠泛化集成或堆叠。
具体来说,您了解到:
- 堆叠是一种集成机器学习算法,它学习如何最好地组合来自多个表现良好的机器学习模型的预测。
- Sklearn 库提供了 Python 中堆叠集成的标准实现。
- 如何使用堆叠集成进行回归和分类预测建模?
你有什么问题吗? 在下面的评论中提问,我会尽力回答。
集成学习中强学习器与弱学习器
常用弱学习器和强学习器来描述集成学习技术。
例如,我们可能希望从许多弱学习器的预测中构建一个强学习器。事实上,这是集成学习算法提升类的明确目标。
尽管我们可以将模型描述为弱模型或强模型,但这些术语有一个特定的形式定义,并被用作计算学习理论领域一个重要发现的基础。
在本教程中,您将发现弱学习器和强学习器及其与集成学习的关系。
完成本教程后,您将知道:
- 弱学习器是比随机猜测表现稍好的模型。
- 强学习器是具有任意好的准确性的模型。
- 弱学习器和强学习器是来自计算学习理论的工具,并且为集成方法的提升类的发展提供基础。
用我的新书Python 集成学习算法启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
集体学习的强学习器 vs 弱学习器 图片由 G .拉马尔提供,保留部分权利。
教程概述
本教程分为三个部分;它们是:
- 弱学习器
- 优秀的学习器
- 弱与强的学习器和提升
弱学习器
弱分类器是一种二进制分类模型,其表现略好于随机猜测。
弱学习器产生的分类器只比随机分类稍微精确一点。
—第 21 页,使用集成方法的模式分类,2010。
这意味着模型将做出已知具有某种技能的预测,例如使模型的能力变弱,尽管不会弱到模型没有技能,例如表现比随机更差。
- 弱分类器:形式上,达到略高于 50%准确率的分类器。
弱分类器有时被称为“弱学习器”或“基础学习器,这个概念可以被推广到二分类之外。
虽然弱学习器的概念在二进制分类的背景下被很好地理解,但它可以被通俗地理解为任何比简单预测方法表现稍好的模型。从这个意义上说,它是思考分类器能力和集合组成的有用工具。
- 弱学习器:通俗来说,表现比幼稚模型略好的模型。
更正式地说,这个概念已经被推广到多类分类,并且有着不同的含义,超过了 50%的准确率。
对于二分类,众所周知,对弱学习器的确切要求是要优于随机猜测。[……]请注意,要求基础学习器优于随机猜测对于多类问题来说太弱了,然而要求优于 50%的准确率太严格了。
—第 46 页,集合方法,2012。
它基于形式计算学习理论,提出了一类具有弱可学习性的学习方法,这意味着它们比随机猜测表现得更好。弱可学习性是作为更理想的强可学习性的简化而提出的,其中可学习性实现了任意好的分类准确率。
一个较弱的可学习性模型,称为弱可学习性,放弃了学习器能够达到任意高准确率的要求;弱学习算法只需要输出一个比随机猜测表现稍好的假设(通过逆多项式)。
——弱可学性的力量,1990。
这是一个有用的概念,因为它经常被用来描述集成学习算法的贡献成员的能力。例如,有时引导聚合的成员被称为弱学习器,而不是强学习器,至少在术语的口语意义上是这样。
更具体地说,弱学习器是集成学习算法的增强类的基础。
术语增强指的是能够将弱学习器转化为强学习器的一系列算法。
—第 23 页,集合方法,2012。
最常用的弱学习模型是决策树。这是因为在施工过程中,树的弱点可以通过树的深度来控制。
对于二进制分类任务,最弱的决策树由单个节点组成,该节点对一个输入变量做出决策并输出二进制预测。这通常被称为“决策树桩”
这里弱分类器只是一个“树桩”:一个双端节点分类树。
—第 339 页,统计学习的要素,2016。
它经常被用作弱学习器,以至于决策树桩和弱学习器实际上是同义词。
- 决策树桩:单节点对一个输入变量进行运算的决策树,其输出直接进行预测。
尽管如此,其他模型也可以配置为弱学习器。
因为提升需要一个弱的学习器,几乎任何带有调整参数的技术都可以变成弱的学习器。事实证明,树木是提升学习能力的绝佳基础…
—第 205 页,应用预测建模,2013 年。
虽然不被正式称为弱学习器,但我们可以考虑以下作为候选弱学习模型:
- k-最近邻,k=1 操作一个或一个子集的输入变量。
- 多层感知器,单个节点对一个或一个子集的输入变量进行操作。
- 朴素贝叶斯,对单个输入变量进行运算。
既然我们已经熟悉了一个弱学习器,让我们来仔细看看强学习器。
优秀的学习器
强分类器是一种二进制分类模型,其表现优于随机猜测。
一类概念是可学习的(或强可学习的),如果存在多项式时间算法,该算法对该类中的所有概念实现了低误差和高置信度。
——弱可学性的力量,1990。
这有时被解释为训练或保持数据集上的完美技能,尽管更可能指的是“好的”或“有用地熟练的”模型。
- 强分类器:形式上,达到任意好准确率的分类器。
我们寻求预测建模问题的强分类器。建模项目的目标是开发一个强大的分类器,以高置信度做出最正确的预测。
同样,虽然强分类器的概念对于二进制分类来说很好理解,但它可以推广到其他问题类型,我们可以不太正式地将这个概念解释为一个表现良好的模型,也许是接近最优的。
- 强学习器:通俗来说,就是一个和幼稚模型相比表现非常好的模型。
当我们在数据集上直接拟合机器学习模型时,我们试图开发一个强模型。例如,我们可以将以下算法视为用于拟合通俗意义上的强模型的技术,其中每种方法的超参数都针对目标问题进行了调整:
- 逻辑回归。
- 支持向量机。
- k-最近邻居。
以及更多在前面章节中列出的或者你可能熟悉的方法。
强学习是我们所追求的,我们可以将他们的能力与弱学习器进行对比,尽管我们也可以从弱学习器中构建强学习器。
弱与强的学习器和提升
我们已经确定弱学习器的表现略好于随机,并且强学习器是好的甚至接近最优的,并且我们寻求的预测建模项目是后者。
在计算学习理论中,特别是 PAC 学习中,弱可学习性和强可学习性的形式分类被定义为两者是否等价的开放问题。
这里提出的证据是建设性的;描述了一种显式方法,用于将弱学习算法直接转换成实现任意准确率的算法。该构造使用过滤来修改示例的分布,从而迫使弱学习算法关注分布中较难学习的部分。
——弱可学性的力量,1990。
后来才发现,它们确实是等价的。更重要的是,一个强有力的学习器可以由许多弱的学习器构成,正式定义。这为集成学习方法的提升类提供了基础。
主要结果是证明了强可学习性和弱可学习性可能惊人的等价性。
——弱可学性的力量,1990。
尽管这一理论发现已经有了,但在第一批可行的提升方法被开发出来并实现之前,仍然需要数年的时间。
最值得注意的是,自适应增强(AdaBoost)是第一个成功的增强方法,后来导致了大量的方法,最终导致了今天非常成功的技术,如梯度提升和实现,如极限梯度提升(XGBoost)。
弱学习器的集合主要在机器学习社区中研究。在这个线索中,研究人员经常研究弱学习器,并试图设计强大的算法来提升从弱到强的表现。这一系列工作导致了著名的集成方法的诞生,如 AdaBoost、Bagging 等。、以及关于为什么以及如何将弱学习器提升到强学习器的理论理解。
—第 16 页,集合方法,2012。
一般来说,提升集成的目标是为预测性学习问题培养大量弱学习器,然后最好地组合它们,以实现强学习器。这是一个很好的目标,因为弱学习器容易准备但不可取,而强学习器很难准备并且非常可取。
由于强学习器是可取的但很难获得,而弱学习器在实际实践中很容易获得,这一结果为通过集成方法产生强学习器开辟了一个有希望的方向。
—第 16-17 页,集合方法,2012。
- 弱学习器:容易准备,但由于技能低不可取。
- 学习能力强:很难准备,但因为技术高而令人向往。
实现这一点的过程是顺序开发弱学习器,并将他们添加到集合中,其中每个弱学习器都以一种方式进行训练,以更加关注问题域中先前模型出错的部分。尽管所有的增强技术都遵循这个具有特定差异和优化的一般过程,但是弱学习器和强学习器的概念对于机器学习和集成学习来说是一个更普遍的有用概念。
例如,我们已经看到如何描述预测模型的目标是开发一个强模型。通常的做法是根据基线或原始模型评估模型的表现,例如二进制分类的随机预测。一个弱的学习器非常像天真的模型,尽管稍微熟练并且使用来自问题领域的最少信息,而不是完全天真的。
考虑到虽然我们在自举聚合(bagging)中没有从技术上构造弱学习器,这意味着成员不是决策树桩,但是我们确实致力于创建更弱的决策树来组成集成。这通常是通过在采样的数据子集上拟合树,而不是修剪树来实现的,这允许它们稍微过度填充训练数据。
对于分类,我们可以根据独立弱学习器的共识来理解 bagging 效应
—第 286 页,统计学习的要素,2016。
这两种变化都是为了寻找相关性较低的树,但具有训练较弱(但可能不是较弱)的模型来组成集合的效果。
- 装袋:明确训练较弱(但不算弱)的学习器。
考虑堆叠泛化(堆叠),它训练一个模型,以最好地组合来自多个不同模型的预测,以适合同一训练数据集。每个贡献的 0 级模型实际上都是一个强大的学习器,元 1 级模型试图通过组合来自强大模型的预测来构建一个更强大的模型。
- 叠加:明确组合强学习器的预测。
专家混合(MoE)以类似的方式运行,训练多个强模型(专家),通过元模型、门控网络和梳理方法将它们组合成有希望更强的模型。
专家混合也可以看作是一种分类器选择算法,其中个体分类器被训练成为特征空间某一部分的专家。在这种情况下,个体分类器确实被训练成为专家,因此通常不是弱分类器
—第 16 页,集成机器学习,2012。
这突出表明,尽管弱和强的可学习性和学习器是增强的重要理论发现和基础,但是这些分类器的更一般化的思想是设计和选择集成方法的有用工具。
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
报纸
- 弱可学性的力量,1990。
书
- 使用集成方法的模式分类,2010。
- 集成方法,2012。
- 集成机器学习,2012。
- 数据挖掘中的集成方法,2010。
- 统计学习的要素,2016。
- 应用预测建模,2013。
文章
- 一起学习,维基百科。
- Boosting(机器学习),维基百科。
摘要
在本教程中,您发现了弱学习器和强学习器及其与集成学习的关系。
具体来说,您了解到:
- 弱学习器是比随机猜测表现稍好的模型。
- 强学习器是具有任意好的准确性的模型。
- 弱学习器和强学习器是来自计算学习理论的工具,并且为集成方法的提升类的发展提供基础。
你有什么问题吗? 在下面的评论中提问,我会尽力回答。
如何在 Python 中开发超级学习器集成
最后更新于 2021 年 8 月 24 日
为预测建模问题选择机器学习算法涉及使用 K 折交叉验证来评估许多不同的模型和模型配置。
超级学习器是一种集成机器学习算法,它结合了您可能为预测建模问题调查的所有模型和模型配置,并使用它们来做出与您可能调查的任何单个模型一样好或更好的预测。
超级学习器算法是堆叠概括的应用,称为堆叠或混合,应用于 k 折叠交叉验证,其中所有模型使用相同的 k 折叠数据分割,元模型适合每个模型的折外预测。
在本教程中,您将发现超级学习器集成机器学习算法。
完成本教程后,您将知道:
- 超级学习器是在 k 倍交叉验证期间使用折外预测的堆叠概括的应用。
- 超级学习器集成算法使用 Sklearn 模型在 Python 中直接实现。
- ML-集成(mlens)库提供了一个方便的实现,允许超级学习器只需几行代码就能适应和使用。
用我的新书Python 集成学习算法启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
- 2020 年 1 月更新:针对 Sklearn v0.22 API 的变化进行了更新。
如何开发 Python 超级学习器集成 图片由马克·戈恩提供,保留部分权利。
教程概述
本教程分为三个部分;它们是:
- 什么是超级学习器?
- 使用 Sklearn 手动培养超级学习器
- 超级学习器与最大似然集成库
什么是超级学习器?
预测建模问题有数百种模型可供选择;哪一个最好?
然后,在选择了一个模型之后,您如何为您的特定数据集最好地配置它?
这些都是应用机器学习中的开放性问题。目前我们最好的答案是使用经验实验来测试和发现什么最适合您的数据集。
在实践中,对于给定的预测问题和数据集,通常不可能先验地知道哪个学习器表现最好。
——超级学习器,2007 年。
这包括选择可能适合您的回归或分类问题的许多不同算法,并使用重采样技术评估它们在数据集上的表现,例如 k 倍交叉验证。
然后选择根据 k 倍交叉验证在数据集上表现最好的算法,适合所有可用数据,然后您可以开始使用它进行预测。
还有一种替代方法。
考虑到您已经在数据集上安装了许多不同的算法,并且一些算法已经用不同的配置进行了多次评估。您的问题可能有几十个或几百个不同的模型。为什么不使用所有这些模型,而使用组中最好的模型呢?
这就是所谓的“超级学习器”集成算法背后的直觉。
超级学习器算法包括首先预定义数据的 k 倍分割,然后评估同一分割数据上的所有不同算法和算法配置。然后,所有超出范围的预测都被保留下来,并用于训练一种算法,学习如何最好地组合预测。
这些算法可能在所使用的协变量子集、基函数、损失函数、搜索算法和调谐参数范围等方面有所不同。
——预测中的超级学习器,2010。
这个模型的结果应该不会比 k 倍交叉验证期间评估的最佳表现模型差,并且有可能比任何单一模型表现更好。
超级学习器算法是由来自伯克利的马克·范德莱恩、T2、埃里克·波利和 T4 在他们 2007 年的论文《超级学习器》中提出的它发表在一份生物学杂志上,该杂志可能不受更广泛的机器学习社区的影响。
超级学习器技术是一般方法的一个例子,简称为“堆叠概括”或“堆叠”,在应用机器学习中被称为混合,因为通常使用线性模型作为元模型。
超级学习器与神经网络环境中引入的堆叠算法有关…
——预测中的超级学习器,2010。
有关主题堆叠的更多信息,请参见帖子:
我们可以把“超级学习器”想象成一种专门针对 k-fold 交叉验证的堆叠的具体配置。
我有时见过这种类型的混合集成,称为交叉验证集成。
该程序可总结如下:
- 1.选择训练数据集的 k 倍分割。
- 2.选择 m 个基本模型或模型配置。
- 3.对于每个基本模型:
- a.使用 k 倍交叉验证进行评估。
- b.存储所有超出范围的预测。
- c.在完整的训练数据集上拟合模型并存储。
- 4.根据不一致的预测建立一个元模型。
- 5.在保持数据集上评估模型或使用模型进行预测。
下图取自原始论文,总结了这个数据流。
超级学习器算法的数据流图 取自“超级学习器”
让我们仔细看看这个过程中可能存在的一些常见症结。
问:元模型的输入和输出是什么?
元模型接受来自基本模型的预测作为输入,并预测训练数据集的目标作为输出:
- 输入:基础模型的预测。
- 输出:训练数据集的预测。
例如,如果我们有 50 个基本模型,那么一个输入样本将是一个具有 50 个值的向量,向量中的每个值代表来自训练数据集的一个样本的一个基本模型的预测。
如果我们在训练数据集中有 1000 个示例(行)和 50 个模型,那么元模型的输入数据将是 1000 行和 50 列。
问:元模型不会过度训练数据吗?
可能不会。
这是超级学习器的诀窍,也是一般的堆叠概括过程。
元模型的输入是超折叠(超样本)预测。总的来说,模型的异常预测代表了模型对训练中没有看到的数据进行预测的技能或能力。
通过在其他模型的样本外预测上训练元模型,元模型学习如何校正每个模型的样本外预测,以及如何最佳地组合来自多个模型的样本外预测;实际上,它同时完成了这两项任务。
重要的是,为了了解元模型的真正能力,必须对新的样本外数据进行评估。也就是说,不用于训练基本模型的数据。
问:这个可以用于回归和分类吗?
是的,在回归(预测数值)的论文中有描述。
它也可以用于分类(预测类标签),尽管在组合预测时,最好预测概率以赋予元模型更大的粒度。
问:为什么我们要在整个训练数据集上拟合每个基础模型?
每个基础模型都适合整个训练数据集,以便以后可以使用该模型对训练过程中没有看到的新示例进行预测。
在超级学习器需要预测之前,严格不需要这一步。
问:我们如何做预测?
为了对新样本(数据行)进行预测,首先,将数据行作为输入提供给每个基本模型,以从每个模型生成预测。
然后将基础模型的预测连接成一个向量,并作为输入提供给元模型。元模型然后对数据行进行最终预测。
我们可以将此过程总结如下:
- 1.取一个模型在训练中没有看到的样本。
- 2.对于每个基础模型:
- a.给定样本进行预测。
- b.商店预测。
- 3.将子模型中的预测连接成一个向量。
- 4.提供向量作为元模型的输入,以进行最终预测。
现在我们已经熟悉了超级学习器算法,让我们来看一个工作示例。
使用 Sklearn 手动培养超级学习器
超级学习器算法在 Sklearn Python 机器学习库之上实现起来相对简单。
在本节中,我们将为回归和分类开发一个超级学习的例子,您可以根据自己的问题进行调整。
回归超级学习器
我们将使用make _ revolution()测试问题,生成 1000 个示例(行)和 100 个特征(列)。这是一个简单的回归问题,输入和输出之间存在线性关系,并带有附加噪声。
我们将分割数据,以便 50%用于训练模型,50%用于评估最终的超级模型和基础模型。
...
# create the inputs and outputs
X, y = make_regression(n_samples=1000, n_features=100, noise=0.5)
# split
X, X_val, y, y_val = train_test_split(X, y, test_size=0.50)
print('Train', X.shape, y.shape, 'Test', X_val.shape, y_val.shape)
接下来,我们将定义一系列不同的回归模型。
在这种情况下,我们将使用九种配置适中的不同算法。您可以使用您喜欢的任何型号或型号配置。
下面的 get_models() 函数定义了所有的模型,并将它们作为一个列表返回。
# create a list of base-models
def get_models():
models = list()
models.append(LinearRegression())
models.append(ElasticNet())
models.append(SVR(gamma='scale'))
models.append(DecisionTreeRegressor())
models.append(KNeighborsRegressor())
models.append(AdaBoostRegressor())
models.append(BaggingRegressor(n_estimators=10))
models.append(RandomForestRegressor(n_estimators=10))
models.append(ExtraTreesRegressor(n_estimators=10))
return models
接下来,我们将使用 k 倍交叉验证进行超倍预测,这些预测将用作训练元模型或“T0”超级学习器的数据集。
这包括首先将数据分成 k 个折叠;我们将使用 10。对于每个折叠,我们将在分割的训练部分拟合模型,并在分割的测试部分做出折外的预测。对每个模型重复这一过程,并存储所有超出范围的预测。
每个折外预测将是元模型输入的一列。我们将从每个算法中为一个数据折叠收集列,水平堆叠行。然后,对于我们收集的所有列组,我们将这些行垂直堆叠成一个包含 500 行和 9 列的长数据集。
下面的*get _ out _ of _ fold _ predictions()*函数对给定的测试数据集和模型列表执行此操作;它将返回训练元模型所需的输入和输出数据集。
# collect out of fold predictions form k-fold cross validation
def get_out_of_fold_predictions(X, y, models):
meta_X, meta_y = list(), list()
# define split of data
kfold = KFold(n_splits=10, shuffle=True)
# enumerate splits
for train_ix, test_ix in kfold.split(X):
fold_yhats = list()
# get data
train_X, test_X = X[train_ix], X[test_ix]
train_y, test_y = y[train_ix], y[test_ix]
meta_y.extend(test_y)
# fit and make predictions with each sub-model
for model in models:
model.fit(train_X, train_y)
yhat = model.predict(test_X)
# store columns
fold_yhats.append(yhat.reshape(len(yhat),1))
# store fold yhats as columns
meta_X.append(hstack(fold_yhats))
return vstack(meta_X), asarray(meta_y)
然后,我们可以调用函数来获取模型,调用函数来准备元模型数据集。
...
# get models
models = get_models()
# get out of fold predictions
meta_X, meta_y = get_out_of_fold_predictions(X, y, models)
print('Meta ', meta_X.shape, meta_y.shape)
接下来,我们可以在整个训练数据集上拟合所有的基础模型。
# fit all base models on the training dataset
def fit_base_models(X, y, models):
for model in models:
model.fit(X, y)
然后,我们可以在准备好的数据集上拟合元模型。
在这种情况下,我们将使用线性回归模型作为元模型,就像在原始论文中使用的那样。
# fit a meta model
def fit_meta_model(X, y):
model = LinearRegression()
model.fit(X, y)
return model
接下来,我们可以在保持数据集上评估基础模型。
# evaluate a list of models on a dataset
def evaluate_models(X, y, models):
for model in models:
yhat = model.predict(X)
mse = mean_squared_error(y, yhat)
print('%s: RMSE %.3f' % (model.__class__.__name__, sqrt(mse)))
最后,使用超级学习器(基础和元模型)对保持数据集进行预测,并评估该方法的表现。
下面的 super_learner_predictions()函数将使用元模型对新数据进行预测。
# make predictions with stacked model
def super_learner_predictions(X, models, meta_model):
meta_X = list()
for model in models:
yhat = model.predict(X)
meta_X.append(yhat.reshape(len(yhat),1))
meta_X = hstack(meta_X)
# predict
return meta_model.predict(meta_X)
我们可以调用这个函数并评估结果。
...
# evaluate meta model
yhat = super_learner_predictions(X_val, models, meta_model)
print('Super Learner: RMSE %.3f' % (sqrt(mean_squared_error(y_val, yhat))))
将所有这些结合起来,下面列出了使用 Sklearn 模型进行回归的超级学习器算法的完整示例。
# example of a super learner model for regression
from math import sqrt
from numpy import hstack
from numpy import vstack
from numpy import asarray
from sklearn.datasets import make_regression
from sklearn.model_selection import KFold
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import ElasticNet
from sklearn.neighbors import KNeighborsRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.svm import SVR
from sklearn.ensemble import AdaBoostRegressor
from sklearn.ensemble import BaggingRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import ExtraTreesRegressor
# create a list of base-models
def get_models():
models = list()
models.append(LinearRegression())
models.append(ElasticNet())
models.append(SVR(gamma='scale'))
models.append(DecisionTreeRegressor())
models.append(KNeighborsRegressor())
models.append(AdaBoostRegressor())
models.append(BaggingRegressor(n_estimators=10))
models.append(RandomForestRegressor(n_estimators=10))
models.append(ExtraTreesRegressor(n_estimators=10))
return models
# collect out of fold predictions form k-fold cross validation
def get_out_of_fold_predictions(X, y, models):
meta_X, meta_y = list(), list()
# define split of data
kfold = KFold(n_splits=10, shuffle=True)
# enumerate splits
for train_ix, test_ix in kfold.split(X):
fold_yhats = list()
# get data
train_X, test_X = X[train_ix], X[test_ix]
train_y, test_y = y[train_ix], y[test_ix]
meta_y.extend(test_y)
# fit and make predictions with each sub-model
for model in models:
model.fit(train_X, train_y)
yhat = model.predict(test_X)
# store columns
fold_yhats.append(yhat.reshape(len(yhat),1))
# store fold yhats as columns
meta_X.append(hstack(fold_yhats))
return vstack(meta_X), asarray(meta_y)
# fit all base models on the training dataset
def fit_base_models(X, y, models):
for model in models:
model.fit(X, y)
# fit a meta model
def fit_meta_model(X, y):
model = LinearRegression()
model.fit(X, y)
return model
# evaluate a list of models on a dataset
def evaluate_models(X, y, models):
for model in models:
yhat = model.predict(X)
mse = mean_squared_error(y, yhat)
print('%s: RMSE %.3f' % (model.__class__.__name__, sqrt(mse)))
# make predictions with stacked model
def super_learner_predictions(X, models, meta_model):
meta_X = list()
for model in models:
yhat = model.predict(X)
meta_X.append(yhat.reshape(len(yhat),1))
meta_X = hstack(meta_X)
# predict
return meta_model.predict(meta_X)
# create the inputs and outputs
X, y = make_regression(n_samples=1000, n_features=100, noise=0.5)
# split
X, X_val, y, y_val = train_test_split(X, y, test_size=0.50)
print('Train', X.shape, y.shape, 'Test', X_val.shape, y_val.shape)
# get models
models = get_models()
# get out of fold predictions
meta_X, meta_y = get_out_of_fold_predictions(X, y, models)
print('Meta ', meta_X.shape, meta_y.shape)
# fit base models
fit_base_models(X, y, models)
# fit the meta model
meta_model = fit_meta_model(meta_X, meta_y)
# evaluate base models
evaluate_models(X_val, y_val, models)
# evaluate meta model
yhat = super_learner_predictions(X_val, models, meta_model)
print('Super Learner: RMSE %.3f' % (sqrt(mean_squared_error(y_val, yhat))))
运行该示例首先报告准备好的数据集的形状,然后报告元模型的数据集的形状。
接下来,在保持数据集上报告每个基本模型的表现,最后,在保持数据集上报告超级学习器的表现。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到线性模型在数据集上表现良好,而非线性算法表现不太好。
我们还可以看到,超级学习器超越了所有的基础模型。
Train (500, 100) (500,) Test (500, 100) (500,)
Meta (500, 9) (500,)
LinearRegression: RMSE 0.548
ElasticNet: RMSE 67.142
SVR: RMSE 172.717
DecisionTreeRegressor: RMSE 159.137
KNeighborsRegressor: RMSE 154.064
AdaBoostRegressor: RMSE 98.422
BaggingRegressor: RMSE 108.915
RandomForestRegressor: RMSE 115.637
ExtraTreesRegressor: RMSE 105.749
Super Learner: RMSE 0.546
你可以想象在这个例子中插入各种不同的模型,包括 XGBoost 和 Keras 深度学习模型。
既然我们已经看到了如何为回归开发一个超级学习器,让我们看一个分类的例子。
分类超级学习器
分类的超级学习器算法也差不多。
元学习器的输入可以是类别标签或类别概率,考虑到预测中捕获的粒度或不确定性增加,后者更可能有用。
在这个问题中,我们将使用 make_blobs()测试分类问题,并使用 100 个输入变量和两个类标签的 1000 个示例。
...
# create the inputs and outputs
X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20)
# split
X, X_val, y, y_val = train_test_split(X, y, test_size=0.50)
print('Train', X.shape, y.shape, 'Test', X_val.shape, y_val.shape)
接下来,我们可以更改 get_models() 函数来定义一套线性和非线性分类算法。
# create a list of base-models
def get_models():
models = list()
models.append(LogisticRegression(solver='liblinear'))
models.append(DecisionTreeClassifier())
models.append(SVC(gamma='scale', probability=True))
models.append(GaussianNB())
models.append(KNeighborsClassifier())
models.append(AdaBoostClassifier())
models.append(BaggingClassifier(n_estimators=10))
models.append(RandomForestClassifier(n_estimators=10))
models.append(ExtraTreesClassifier(n_estimators=10))
return models
接下来,我们可以通过调用 predict_proba() 函数来更改*get _ out _ of _ fold _ predictions()*函数来预测概率。
# collect out of fold predictions form k-fold cross validation
def get_out_of_fold_predictions(X, y, models):
meta_X, meta_y = list(), list()
# define split of data
kfold = KFold(n_splits=10, shuffle=True)
# enumerate splits
for train_ix, test_ix in kfold.split(X):
fold_yhats = list()
# get data
train_X, test_X = X[train_ix], X[test_ix]
train_y, test_y = y[train_ix], y[test_ix]
meta_y.extend(test_y)
# fit and make predictions with each sub-model
for model in models:
model.fit(train_X, train_y)
yhat = model.predict_proba(test_X)
# store columns
fold_yhats.append(yhat)
# store fold yhats as columns
meta_X.append(hstack(fold_yhats))
return vstack(meta_X), asarray(meta_y)
在 fit_meta_model() 函数中,将使用逻辑回归算法而不是线性回归算法作为元算法。
# fit a meta model
def fit_meta_model(X, y):
model = LogisticRegression(solver='liblinear')
model.fit(X, y)
return model
分类准确率将用于报告模型表现。
下面列出了使用 Sklearn 模型进行分类的超级学习器算法的完整示例。
# example of a super learner model for binary classification
from numpy import hstack
from numpy import vstack
from numpy import asarray
from sklearn.datasets import make_blobs
from sklearn.model_selection import KFold
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import ExtraTreesClassifier
# create a list of base-models
def get_models():
models = list()
models.append(LogisticRegression(solver='liblinear'))
models.append(DecisionTreeClassifier())
models.append(SVC(gamma='scale', probability=True))
models.append(GaussianNB())
models.append(KNeighborsClassifier())
models.append(AdaBoostClassifier())
models.append(BaggingClassifier(n_estimators=10))
models.append(RandomForestClassifier(n_estimators=10))
models.append(ExtraTreesClassifier(n_estimators=10))
return models
# collect out of fold predictions form k-fold cross validation
def get_out_of_fold_predictions(X, y, models):
meta_X, meta_y = list(), list()
# define split of data
kfold = KFold(n_splits=10, shuffle=True)
# enumerate splits
for train_ix, test_ix in kfold.split(X):
fold_yhats = list()
# get data
train_X, test_X = X[train_ix], X[test_ix]
train_y, test_y = y[train_ix], y[test_ix]
meta_y.extend(test_y)
# fit and make predictions with each sub-model
for model in models:
model.fit(train_X, train_y)
yhat = model.predict_proba(test_X)
# store columns
fold_yhats.append(yhat)
# store fold yhats as columns
meta_X.append(hstack(fold_yhats))
return vstack(meta_X), asarray(meta_y)
# fit all base models on the training dataset
def fit_base_models(X, y, models):
for model in models:
model.fit(X, y)
# fit a meta model
def fit_meta_model(X, y):
model = LogisticRegression(solver='liblinear')
model.fit(X, y)
return model
# evaluate a list of models on a dataset
def evaluate_models(X, y, models):
for model in models:
yhat = model.predict(X)
acc = accuracy_score(y, yhat)
print('%s: %.3f' % (model.__class__.__name__, acc*100))
# make predictions with stacked model
def super_learner_predictions(X, models, meta_model):
meta_X = list()
for model in models:
yhat = model.predict_proba(X)
meta_X.append(yhat)
meta_X = hstack(meta_X)
# predict
return meta_model.predict(meta_X)
# create the inputs and outputs
X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20)
# split
X, X_val, y, y_val = train_test_split(X, y, test_size=0.50)
print('Train', X.shape, y.shape, 'Test', X_val.shape, y_val.shape)
# get models
models = get_models()
# get out of fold predictions
meta_X, meta_y = get_out_of_fold_predictions(X, y, models)
print('Meta ', meta_X.shape, meta_y.shape)
# fit base models
fit_base_models(X, y, models)
# fit the meta model
meta_model = fit_meta_model(meta_X, meta_y)
# evaluate base models
evaluate_models(X_val, y_val, models)
# evaluate meta model
yhat = super_learner_predictions(X_val, models, meta_model)
print('Super Learner: %.3f' % (accuracy_score(y_val, yhat) * 100))
像以前一样,报告数据集和准备好的元数据集的形状,然后是基础模型在保持数据集上的表现,最后是超级模型本身在保持数据集上的表现。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到超级学习器的表现比基本学习器算法稍好。
Train (500, 100) (500,) Test (500, 100) (500,)
Meta (500, 18) (500,)
LogisticRegression: 96.600
DecisionTreeClassifier: 74.400
SVC: 97.400
GaussianNB: 97.800
KNeighborsClassifier: 95.400
AdaBoostClassifier: 93.200
BaggingClassifier: 84.400
RandomForestClassifier: 82.800
ExtraTreesClassifier: 82.600
Super Learner: 98.000
超级学习器与最大似然集成库
手动实现超级学习器是一个很好的练习,但并不理想。
我们可能会在实现中引入错误,并且所列出的示例没有利用多核来加快执行速度。
谢天谢地, Sebastian Flennerhag 在他的ML-integration(mlens)Python 库中提供了一个高效且经过测试的超级学习器算法和其他集成算法的实现。它专门设计用于 Sklearn 模型。
首先,必须安装库,这可以通过 pip 实现,如下所示:
sudo pip install mlens
接下来,可以定义一个超级学习器类,通过调用 add() 函数添加模型,通过调用 add_meta() 函数添加元学习器,然后像其他 Sklearn 模型一样使用模型。
...
# configure model
ensemble = SuperLearner(...)
# add list of base learners
ensemble.add(...)
# add meta learner
ensemble.add_meta(...)
# use model ...
我们可以用这个类来解决前一节中的回归和分类问题。
用最大似然集成库进行回归的超级学习器
首先,我们可以为我们的问题定义一个计算 RMSE 的函数,超级学习器可以用它来评估基本模型。
# cost function for base models
def rmse(yreal, yhat):
return sqrt(mean_squared_error(yreal, yhat))
接下来,我们可以为超级载体配置 10 倍交叉验证、我们的评估函数,以及在准备超倍预测作为元模型输入时使用整个训练数据集。
下面的*get _ super _ leaner()*函数实现了这一点。
# create the super learner
def get_super_learner(X):
ensemble = SuperLearner(scorer=rmse, folds=10, shuffle=True, sample_size=len(X))
# add base models
models = get_models()
ensemble.add(models)
# add the meta model
ensemble.add_meta(LinearRegression())
return ensemble
然后,我们可以在训练数据集上拟合模型。
...
# fit the super learner
ensemble.fit(X, y)
一旦拟合,我们可以通过访问模型上的“数据”属性,使用 k 倍交叉验证获得训练数据集中每个基础模型的表现的良好报告。
...
# summarize base learners
print(ensemble.data)
仅此而已。
将这些联系在一起,下面列出了使用 mlens 回归库评估超级学习器的完整示例。
# example of a super learner for regression using the mlens library
from math import sqrt
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import ElasticNet
from sklearn.neighbors import KNeighborsRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.svm import SVR
from sklearn.ensemble import AdaBoostRegressor
from sklearn.ensemble import BaggingRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import ExtraTreesRegressor
from mlens.ensemble import SuperLearner
# create a list of base-models
def get_models():
models = list()
models.append(LinearRegression())
models.append(ElasticNet())
models.append(SVR(gamma='scale'))
models.append(DecisionTreeRegressor())
models.append(KNeighborsRegressor())
models.append(AdaBoostRegressor())
models.append(BaggingRegressor(n_estimators=10))
models.append(RandomForestRegressor(n_estimators=10))
models.append(ExtraTreesRegressor(n_estimators=10))
return models
# cost function for base models
def rmse(yreal, yhat):
return sqrt(mean_squared_error(yreal, yhat))
# create the super learner
def get_super_learner(X):
ensemble = SuperLearner(scorer=rmse, folds=10, shuffle=True, sample_size=len(X))
# add base models
models = get_models()
ensemble.add(models)
# add the meta model
ensemble.add_meta(LinearRegression())
return ensemble
# create the inputs and outputs
X, y = make_regression(n_samples=1000, n_features=100, noise=0.5)
# split
X, X_val, y, y_val = train_test_split(X, y, test_size=0.50)
print('Train', X.shape, y.shape, 'Test', X_val.shape, y_val.shape)
# create the super learner
ensemble = get_super_learner(X)
# fit the super learner
ensemble.fit(X, y)
# summarize base learners
print(ensemble.data)
# evaluate meta model
yhat = ensemble.predict(X_val)
print('Super Learner: RMSE %.3f' % (rmse(y_val, yhat)))
运行该示例首先报告每个基本模型的 RMSE(得分-m),然后报告超级学习器本身的 RMSE。
考虑到在后端使用多线程允许使用机器的所有内核,拟合和评估非常快。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到超级学习器表现良好。
请注意,我们无法将表中的基本学习器分数与超级学习器进行比较,因为基本学习器仅在训练数据集上进行评估,而不是在保持数据集上进行评估。
[MLENS] backend: threading
Train (500, 100) (500,) Test (500, 100) (500,)
score-m score-s ft-m ft-s pt-m pt-s
layer-1 adaboostregressor 86.67 9.35 0.56 0.02 0.03 0.01
layer-1 baggingregressor 94.46 11.70 0.22 0.01 0.01 0.00
layer-1 decisiontreeregressor 137.99 12.29 0.03 0.00 0.00 0.00
layer-1 elasticnet 62.79 5.51 0.01 0.00 0.00 0.00
layer-1 extratreesregressor 84.18 7.87 0.15 0.03 0.00 0.01
layer-1 kneighborsregressor 152.42 9.85 0.00 0.00 0.00 0.00
layer-1 linearregression 0.59 0.07 0.02 0.01 0.00 0.00
layer-1 randomforestregressor 93.19 10.10 0.20 0.02 0.00 0.00
layer-1 svr 162.56 12.48 0.03 0.00 0.00 0.00
Super Learner: RMSE 0.571
基于最大似然集成库的超级分类学习器
ML-集成也很容易用于分类问题,遵循相同的一般模式。
在这种情况下,我们将使用分类器模型列表和逻辑回归模型作为元模型。
下面列出了使用 mlens 库为测试分类问题拟合和评估超级学习器模型的完整示例。
# example of a super learner using the mlens library
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import ExtraTreesClassifier
from mlens.ensemble import SuperLearner
# create a list of base-models
def get_models():
models = list()
models.append(LogisticRegression(solver='liblinear'))
models.append(DecisionTreeClassifier())
models.append(SVC(gamma='scale', probability=True))
models.append(GaussianNB())
models.append(KNeighborsClassifier())
models.append(AdaBoostClassifier())
models.append(BaggingClassifier(n_estimators=10))
models.append(RandomForestClassifier(n_estimators=10))
models.append(ExtraTreesClassifier(n_estimators=10))
return models
# create the super learner
def get_super_learner(X):
ensemble = SuperLearner(scorer=accuracy_score, folds=10, shuffle=True, sample_size=len(X))
# add base models
models = get_models()
ensemble.add(models)
# add the meta model
ensemble.add_meta(LogisticRegression(solver='lbfgs'))
return ensemble
# create the inputs and outputs
X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20)
# split
X, X_val, y, y_val = train_test_split(X, y, test_size=0.50)
print('Train', X.shape, y.shape, 'Test', X_val.shape, y_val.shape)
# create the super learner
ensemble = get_super_learner(X)
# fit the super learner
ensemble.fit(X, y)
# summarize base learners
print(ensemble.data)
# make predictions on hold out set
yhat = ensemble.predict(X_val)
print('Super Learner: %.3f' % (accuracy_score(y_val, yhat) * 100))
运行该示例总结了数据集的形状、基础模型的表现,以及超级学习器在保持数据集上的表现。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
同样,我们可以看到超级学习器在这个测试问题上表现良好,更重要的是,与上一节中的手动示例相比,非常快速地适应和评估。
[MLENS] backend: threading
Train (500, 100) (500,) Test (500, 100) (500,)
score-m score-s ft-m ft-s pt-m pt-s
layer-1 adaboostclassifier 0.90 0.04 0.51 0.05 0.04 0.01
layer-1 baggingclassifier 0.83 0.06 0.21 0.01 0.01 0.00
layer-1 decisiontreeclassifier 0.68 0.07 0.03 0.00 0.00 0.00
layer-1 extratreesclassifier 0.80 0.05 0.09 0.01 0.00 0.00
layer-1 gaussiannb 0.96 0.04 0.01 0.00 0.00 0.00
layer-1 kneighborsclassifier 0.90 0.03 0.00 0.00 0.03 0.01
layer-1 logisticregression 0.93 0.03 0.01 0.00 0.00 0.00
layer-1 randomforestclassifier 0.81 0.06 0.09 0.03 0.00 0.00
layer-1 svc 0.96 0.03 0.10 0.01 0.00 0.00
Super Learner: 97.400
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
教程
书
- 针对性学习:观察和实验数据的因果推断,2011。
- 数据科学中的目标学习:复杂纵向研究的因果推理,2018。
报纸
软件
- 超级学习器:超级学习器预测,CRAN 。
- 超级载体:预测模型集成方法,GitHub 。
- 超级载体指南,晕影,2017。
Python 软件
摘要
在本教程中,您发现了超级学习器集成机器学习算法。
具体来说,您了解到:
- 超级学习器是在 k 倍交叉验证期间使用折外预测的堆叠概括的应用。
- 超级学习器集成算法使用 Sklearn 模型在 Python 中直接实现。
- ML-集成(mlens)库提供了一个方便的实现,允许超级学习器只需几行代码就能适应和使用。
你有什么问题吗? 在下面的评论中提问,我会尽力回答。
集成学习算法的温和介绍
最后更新于 2021 年 4 月 27 日
集成学习是一种通用的机器学习元方法,通过组合来自多个模型的预测来寻求更好的预测表现。
尽管有看似无限多的集成可以为您的预测建模问题开发,但有三种方法主导着集成学习领域。如此之多,以至于除了算法本身,每一个都是一个研究领域,产生了许多更专业的方法。
集成学习方法的三个主要类别是装袋、堆叠和提升,对每种方法都有详细的了解并在您的预测建模项目中加以考虑是很重要的。
但是,在此之前,在对数学和代码进行分层之前,您需要对这些方法以及每种方法背后的关键思想进行温和的介绍。
在本教程中,您将发现机器学习的三种标准集成学习技术。
完成本教程后,您将知道:
- 装袋包括在同一数据集的不同样本上拟合许多决策树,并对预测进行平均。
- 堆叠包括在同一数据上拟合许多不同的模型类型,并使用另一个模型来学习如何最好地组合预测。
- 增强包括按顺序添加集成成员,这些成员修正由先前模型做出的预测,并输出预测的加权平均值。
用我的新书Python 集成学习算法启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
集成学习算法的温和介绍拉吉夫·布坦摄,版权所有。
教程概述
本教程分为四个部分;它们是:
- 标准集成学习策略
- 装袋集成学习
- 堆叠集成学习
- 促进集成学习
标准集成学习策略
集成学习是指将两个或多个模型的预测结合起来的算法。
尽管实现这一点的方法几乎是无限的,但在实践中最常讨论和使用的集成学习技术可能有三类。它们之所以受欢迎,很大程度上是因为它们易于实现,并且在广泛的预测建模问题上取得了成功。
在过去的几年中,已经开发了大量基于集成的分类器。然而,这些算法中的许多都是一些精选的少数成熟算法的变体,这些算法的能力也得到了广泛的测试和广泛的报道。
—第 11 页,集成机器学习,2012。
鉴于它们的广泛使用,我们可以将其称为“标准”集成学习策略;它们是:
- 装袋。
- 堆叠。
- 提升。
有一种算法描述了每种方法,尽管更重要的是,每种方法的成功都催生了无数的扩展和相关技术。因此,将每一个都描述为集成学习的一类技术或标准方法更有用。
与其深入研究每种方法的细节,不如逐步了解、总结和对比每种方法。同样重要的是要记住,尽管这些方法的讨论和使用无处不在,但这三种方法本身并不能定义集成学习的范围。
接下来,让我们仔细看看装袋。
装袋集成学习
Bootstrap 聚合,简称 bagging,是一种通过改变训练数据来寻找一组不同的集成成员的集成学习方法。
Bagging 这个名字来自 Bootstrap AGGregatING 的缩写。顾名思义,装袋的两个关键要素是引导和聚合。
—第 48 页,集合方法,2012。
这通常涉及使用单一的机器学习算法,几乎总是一个未运行的决策树,并在同一训练数据集的不同样本上训练每个模型。然后使用简单的统计数据,如投票或平均,将全体成员做出的预测结合起来。
通过在其上训练每个分类器的自举副本内的变化,以及通过使用相对较弱的分类器来确保集合中的多样性,所述相对较弱的分类器的决策边界相对于训练数据中相对较小的扰动而可测量地变化。
—第 11 页,集成机器学习,2012。
该方法的关键是数据集的每个样本准备训练集合成员的方式。每个模型都有自己独特的数据集样本。
示例(行)是从数据集中随机抽取的,尽管进行了替换。
Bagging 采用 bootstrap 分布来生成不同的基础学习器。换句话说,它应用自举采样来获得用于训练基础学习器的数据子集。
—第 48 页,集合方法,2012。
替换意味着如果选择了一行,它将返回到训练数据集中,以便在同一训练数据集中进行可能的重新选择。这意味着对于给定的训练数据集,可以零次、一次或多次选择一行数据。
这被称为引导样本。这是一种常用于小数据集统计中的技术,用于估计数据样本的统计值。通过准备多个不同的自举样本并估计统计量和计算估计值的平均值,可以实现比直接从数据集简单估计更好的期望量的总体估计。
以同样的方式,可以准备多个不同的训练数据集,用于估计预测模型,并进行预测。对模型间的预测进行平均通常比直接在训练数据集上拟合单个模型得到更好的预测。
我们可以将装袋的关键要素总结如下:
- 训练数据集的引导样本。
- 未标记的决策树适合每个样本。
- 简单的投票或平均预测。
总的来说,bagging 的贡献在于用于拟合每个集成成员的训练数据的变化,这反过来导致了熟练但不同的模型。
装袋集成
这是一种通用方法,易于扩展。例如,可以引入对训练数据集的更多改变,可以替换适合训练数据的算法,并且可以修改用于组合预测的机制。
许多流行的集成算法都基于这种方法,包括:
- 袋装决策树(标准袋装)
- 随机森林
- 额外树
接下来,让我们仔细看看堆叠。
堆叠集成学习
堆叠泛化,简称堆叠,是一种集成方法,通过改变适合训练数据的模型类型并使用模型组合预测来寻找不同的成员组。
堆叠是一个通用的过程,在这个过程中,一个学习器被训练来组合各个学习器。这里,个体学习器被称为第一级学习器,而组合者被称为第二级学习器或元学习器。
—第 83 页,集合方法,2012。
叠加有自己的术语,其中集合成员被称为 0 级模型,用于组合预测的模型被称为 1 级模型。
模型的两级层次结构是最常见的方法,尽管可以使用更多层的模型。例如,我们可能有 3 个或 5 个一级模型和一个二级模型来组合一级模型的预测,以进行预测,而不是一个一级模型。
堆叠可能是最流行的元学习技术。通过使用元学习器,该方法试图归纳哪些分类器是可靠的,哪些是不可靠的。
—第 82 页,使用集成方法的模式分类,2010。
任何机器学习模型都可以用于聚合预测,尽管通常使用线性模型,例如用于回归的线性回归和用于二分类的逻辑回归。这促使模型的复杂性停留在较低层次的集合成员模型和简单模型上,以学习如何利用各种各样的预测。
使用可训练的组合器,可以确定哪些分类器可能在特征空间的哪个部分成功,并相应地组合它们。
—第 15 页,集成机器学习,2012。
我们可以将堆叠的关键要素总结如下:
- 未更改的训练数据集。
- 每个集成成员有不同的机器学习算法。
- 机器学习模型学习如何最好地组合预测。
多样性来自用作集成成员的不同机器学习模型。
因此,希望使用一套以非常不同的方式学习或构建的模型,确保它们做出不同的假设,进而具有较少的相关预测误差。
叠加集成
许多流行的集成算法都基于这种方法,包括:
- 堆叠模型(规范堆叠)
- 混合
- 太棒了
接下来,让我们仔细看看 boosting。
促进集成学习
Boosting 是一种集成方法,旨在改变训练数据,将注意力集中在训练数据集上以前的拟合模型出错的例子上。
在增强过程中,[……]每个后续分类器的训练数据集越来越关注由先前生成的分类器错误分类的实例。
—第 13 页,集成机器学习,2012。
提升集成的关键特性是校正预测误差的想法。模型被拟合并顺序地添加到集合中,使得第二模型试图校正第一模型的预测,第三模型校正第二模型,等等。
这通常包括使用非常简单的决策树,只做一个或几个决定,在 boosting 中称为弱学习器。弱学习器的预测通过简单的投票或平均进行组合,尽管贡献的权重与他们的表现或能力成正比。目标是从许多有目的的“T2”弱学习器中培养出一个所谓的“强学习器”
…一种迭代方法,用于从一组弱分类器中生成一个强分类器,该方法能够实现任意低的训练误差,每个弱分类器几乎不能比随机猜测做得更好。
—第 13 页,集成机器学习,2012。
通常,训练数据集保持不变,取而代之的是,学习算法被修改以基于特定示例(数据行)是否已经被先前添加的集成成员正确或不正确地预测来或多或少地关注它们。例如,可以对数据行进行加权,以指示学习算法在学习模型时必须给予的关注量。
我们可以将提升的关键要素总结如下:
- 将训练数据偏向那些难以预测的例子。
- 迭代地添加集合成员来修正先前模型的预测。
- 使用模型的加权平均值组合预测。
将许多弱学习器组合成强学习器的想法最早是从理论上提出的,许多算法都被提出,但收效甚微。直到自适应 Boosting (AdaBoost) 算法被开发出来,Boosting 才被证明是一种有效的集成方法。
术语增强指的是能够将弱学习器转化为强学习器的一系列算法。
—第 23 页,集合方法,2012。
自 AdaBoost 以来,已经开发了许多增强方法,其中一些,如随机梯度提升,可能是表格(结构化)数据分类和回归的最有效技术之一。
提升集成
总而言之,许多流行的集成算法都基于这种方法,包括:
- 标准升压
- 梯度增压机
- 随机梯度提升(XGBoost 和类似)
这就完成了我们的标准集成学习技巧之旅。
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
书
- 使用集成方法的模式分类,2010。
- 集成方法,2012。
- 集成机器学习,2012。
- 数据挖掘中的集成方法,2010。
文章
- 一起学习,维基百科。
- 引导聚合,维基百科。
- Boosting(机器学习),维基百科。
摘要
在本教程中,您发现了机器学习的三种标准集成学习技术。
具体来说,您了解到:
- 装袋包括在同一数据集的不同样本上拟合许多决策树,并对预测进行平均。
- 堆叠包括在同一数据上拟合许多不同的模型类型,并使用另一个模型来学习如何最好地组合预测。
- 增强包括按顺序添加集成成员,这些成员校正由先前模型做出的预测,并输出预测的加权平均值。
你有什么问题吗? 在下面的评论中提问,我会尽力回答。
如何用 Python 开发投票集成
最后更新于 2021 年 4 月 27 日
投票是一种集成机器学习算法。
对于回归,投票集合包括做出预测,该预测是多个其他回归模型的平均值。
在分类中,硬投票集合包括对来自其他模型的清晰类标签的投票进行求和,并预测投票最多的类。一个软投票集成包括对类别标签的预测概率求和,并预测具有最大和概率的类别标签。
在本教程中,您将发现如何在 Python 中为机器学习算法创建投票集成。
完成本教程后,您将知道:
- 投票集合包括对分类模型做出的预测进行求和,或者对回归模型做出的预测进行平均。
- 投票组合是如何工作的,何时使用投票组合,以及该方法的局限性。
- 如何实现用于分类预测建模的硬投票集成和软投票集成?
用我的新书Python 集成学习算法启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
如何用 Python 开发投票集成 图片由土地管理局提供,保留部分权利。
教程概述
本教程分为四个部分;它们是:
- 投票团
- 投票集成 Scikit-学习应用编程接口
- 分类投票集成
- 用于分类的硬投票集成
- 用于分类的软投票集成
- 回归投票集成
投票团
投票集成(或“多数投票集成”)是一种集成机器学习模型,它结合了来自多个其他模型的预测。
这是一种可以用来提高模型表现的技术,理想情况下比集成中使用的任何单个模型都获得更好的表现。
投票集合通过组合来自多个模型的预测来工作。它可以用于分类或回归。在回归的情况下,这包括计算模型预测的平均值。在分类的情况下,对每个标签的预测进行求和,并预测具有多数票的标签。
- 回归投票集成:预测是贡献模型的平均值。
- 分类投票集成:预测是投稿模型的多数票。
分类的多数票预测有两种方法;他们是硬投票和软投票。
硬投票包括对每个类别标签的预测进行求和,并预测投票最多的类别标签。软投票包括对每个类别标签的预测概率(或类似概率的分数)求和,并预测具有最大概率的类别标签。
- 硬投票。从模型中预测得票最多的班级
- 软投票。从模型中预测概率总和最大的类。
投票集合可以被认为是元模型,模型的模型。
作为一个元模型,它可以用于任何现有的训练机器学习模型的集合,并且现有的模型不需要知道它们正在集成中使用。这意味着您可以探索在任何拟合模型集或子集上使用投票集成来完成预测建模任务。
当您有两个或更多在预测建模任务中表现良好的模型时,投票集合是合适的。集成中使用的模型必须与他们的预测基本一致。
组合输出的一种方法是投票——与装袋中使用的机制相同。然而,(未加权)投票只有在学习方案表现相当好的情况下才有意义。如果三个分类器中有两个做出了非常不正确的预测,我们就有麻烦了!
—第 497 页,数据挖掘:实用机器学习工具与技术,2016。
在以下情况下使用投票集成:
- 集成中的所有模特一般都有同样好的表现。
- 全体模特大多已经同意了。
当投票集合中使用的模型预测清晰的类别标签时,硬投票是合适的。当投票集成中使用的模型预测类成员的概率时,软投票是合适的。软投票可用于不能自然预测类别成员概率的模型,尽管在用于集成(例如支持向量机、k 近邻和决策树)之前可能需要校准它们的类概率分数。
- 硬投票是针对预测类标签的模型。
- 软投票适用于预测类成员概率的模型。
投票集合不能保证比集合中使用的任何单一模型提供更好的表现。如果集合中使用的任何给定模型比投票集合表现得更好,则可能应该使用该模型来代替投票集合。
情况并非总是如此。投票集合可以降低单个模型预测的差异。这可以从回归任务的预测误差的较低方差中看出。这也可以从分类任务准确性的较低差异中看出。这种较低的方差可能导致总体的较低的平均表现,考虑到模型的较高稳定性或置信度,这可能是所希望的。
如果出现以下情况,请使用投票组合:
- 它比集成中使用的任何模型都有更好的表现。
- 它导致比集合中使用的任何模型更低的方差。
投票集成对于使用随机学习算法的机器学习模型特别有用,并且每次在相同的数据集上训练时都会产生不同的最终模型。一个例子是使用随机梯度下降拟合的神经网络。
有关此主题的更多信息,请参见教程:
投票集成的另一个特别有用的情况是,将同一机器学习算法的多次拟合与稍微不同的超参数相结合。
投票组合在以下情况下最有效:
- 组合使用随机学习算法训练的模型的多次拟合。
- 用不同的超参数组合模型的多次拟合。
投票集合的一个限制是,它对所有模型都一视同仁,这意味着所有模型对预测的贡献都是一样的。如果有些模型在某些情况下很好,而在其他情况下很差,这就是一个问题。
解决这个问题的投票集合的扩展是使用贡献模型的加权平均或加权投票。这有时被称为混合。进一步的扩展是使用机器学习模型来学习在进行预测时何时以及信任每个模型的程度。这被称为堆叠概括,简称堆叠。
投票集合的扩展:
- 加权平均集成(混合)。
- 堆叠泛化(堆叠)。
现在我们已经熟悉了投票集成,让我们来仔细看看如何创建投票集成模型。
投票集成 Scikit-学习应用编程接口
投票集成可以从零开始实现,尽管对初学者来说可能很有挑战性。
Sklearn Python 机器学习库为机器学习提供了投票的实现。
它在 0.22 版及更高版本的库中可用。
首先,通过运行以下脚本来确认您使用的是现代版本的库:
# check Sklearn version
import sklearn
print(sklearn.__version__)
运行脚本将打印您的 Sklearn 版本。
您的版本应该相同或更高。如果没有,您必须升级 Sklearn 库的版本。
0.22.1
两个模型的操作方式相同,采用的参数也相同。使用该模型要求您指定一个做出预测并在投票集合中组合的估计器列表。
基本模型列表通过“估计值参数提供。这是一个 Python 列表,其中列表中的每个元素都是一个元组,具有模型的名称和配置的模型实例。列表中的每个模型必须有唯一的名称。
例如,下面定义了两个基本模型:
...
models = [('lr',LogisticRegression()),('svm',SVC())]
ensemble = VotingClassifier(estimators=models)
列表中的每个模型也可以是管道,包括模型在训练数据集上拟合模型之前所需的任何数据准备。
例如:
...
models = [('lr',LogisticRegression()),('svm',make_pipeline(StandardScaler(),SVC()))]
ensemble = VotingClassifier(estimators=models)
使用投票集合进行分类时,可以通过“投票”参数指定投票类型,如硬投票或软投票,并将其设置为字符串“硬”(默认)或“软”。
例如:
...
models = [('lr',LogisticRegression()),('svm',SVC())]
ensemble = VotingClassifier(estimators=models, voting='soft')
现在我们已经熟悉了 Sklearn 中的投票集成 API,让我们来看看一些工作示例。
分类投票集成
在这一节中,我们将研究使用堆叠来解决分类问题。
首先,我们可以使用 make_classification()函数创建一个包含 1000 个示例和 20 个输入特征的合成二进制分类问题。
下面列出了完整的示例。
# test classification dataset
from sklearn.datasets import make_classification
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=2)
# summarize the dataset
print(X.shape, y.shape)
运行该示例将创建数据集并总结输入和输出组件的形状。
(1000, 20) (1000,)
接下来,我们将演示这个数据集的硬投票和软投票。
用于分类的硬投票集成
我们可以用 k 最近邻算法来演示硬投票。
我们可以拟合五个不同版本的 KNN 算法,每个版本在进行预测时使用不同数量的邻居。我们将使用 1、3、5、7 和 9 个邻居(奇数以避免平局)。
我们的期望是,通过组合由每个不同的 KNN 模型预测的预测类别标签,平均而言,硬投票集成将获得比集成中使用的任何独立模型更好的预测表现。
首先,我们可以创建一个名为 get_voting() 的函数,该函数创建每个 KNN 模型,并将这些模型组合成一个硬投票集合。
# get a voting ensemble of models
def get_voting():
# define the base models
models = list()
models.append(('knn1', KNeighborsClassifier(n_neighbors=1)))
models.append(('knn3', KNeighborsClassifier(n_neighbors=3)))
models.append(('knn5', KNeighborsClassifier(n_neighbors=5)))
models.append(('knn7', KNeighborsClassifier(n_neighbors=7)))
models.append(('knn9', KNeighborsClassifier(n_neighbors=9)))
# define the voting ensemble
ensemble = VotingClassifier(estimators=models, voting='hard')
return ensemble
然后,我们可以创建一个要评估的模型列表,包括每个独立版本的 KNN 模型配置和硬投票集合。
这将有助于我们在分类准确率分数的分布方面直接比较 KNN 模型和集合的每个独立配置。下面的 get_models() 函数创建模型列表供我们评估。
# get a list of models to evaluate
def get_models():
models = dict()
models['knn1'] = KNeighborsClassifier(n_neighbors=1)
models['knn3'] = KNeighborsClassifier(n_neighbors=3)
models['knn5'] = KNeighborsClassifier(n_neighbors=5)
models['knn7'] = KNeighborsClassifier(n_neighbors=7)
models['knn9'] = KNeighborsClassifier(n_neighbors=9)
models['hard_voting'] = get_voting()
return models
每个模型将使用重复的 k 倍交叉验证进行评估。
下面的 evaluate_model() 函数获取一个模型实例,并返回分层 10 倍交叉验证的三次重复的分数列表。
# evaluate a give model using cross-validation
def evaluate_model(model, X, y):
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
return scores
然后,我们可以报告每个算法的平均表现,还可以创建一个方框图和触须图来比较每个算法的准确性分数分布。
将这些联系在一起,完整的示例如下所示。
# compare hard voting to standalone classifiers
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import VotingClassifier
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=2)
return X, y
# get a voting ensemble of models
def get_voting():
# define the base models
models = list()
models.append(('knn1', KNeighborsClassifier(n_neighbors=1)))
models.append(('knn3', KNeighborsClassifier(n_neighbors=3)))
models.append(('knn5', KNeighborsClassifier(n_neighbors=5)))
models.append(('knn7', KNeighborsClassifier(n_neighbors=7)))
models.append(('knn9', KNeighborsClassifier(n_neighbors=9)))
# define the voting ensemble
ensemble = VotingClassifier(estimators=models, voting='hard')
return ensemble
# get a list of models to evaluate
def get_models():
models = dict()
models['knn1'] = KNeighborsClassifier(n_neighbors=1)
models['knn3'] = KNeighborsClassifier(n_neighbors=3)
models['knn5'] = KNeighborsClassifier(n_neighbors=5)
models['knn7'] = KNeighborsClassifier(n_neighbors=7)
models['knn9'] = KNeighborsClassifier(n_neighbors=9)
models['hard_voting'] = get_voting()
return models
# evaluate a give model using cross-validation
def evaluate_model(model, X, y):
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
scores = evaluate_model(model, X, y)
results.append(scores)
names.append(name)
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行该示例首先报告每个模型的平均值和标准偏差准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
我们可以看到,与模型的所有独立版本相比,硬投票集成实现了约 90.2%的更好的分类准确率。
>knn1 0.873 (0.030)
>knn3 0.889 (0.038)
>knn5 0.895 (0.031)
>knn7 0.899 (0.035)
>knn9 0.900 (0.033)
>hard_voting 0.902 (0.034)
然后创建一个方块-触须图,比较每个模型的分布准确率分数,让我们清楚地看到,平均而言,硬投票集合比所有独立模型表现更好。
二进制分类中硬投票集成与独立模型的箱图比较
如果我们选择一个硬投票集合作为我们的最终模型,我们可以像任何其他模型一样,拟合并使用它来对新数据进行预测。
首先,硬投票集合适合所有可用数据,然后可以调用 predict() 函数对新数据进行预测。
下面的示例在我们的二进制类别数据集上演示了这一点。
# make a prediction with a hard voting ensemble
from sklearn.datasets import make_classification
from sklearn.ensemble import VotingClassifier
from sklearn.neighbors import KNeighborsClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=2)
# define the base models
models = list()
models.append(('knn1', KNeighborsClassifier(n_neighbors=1)))
models.append(('knn3', KNeighborsClassifier(n_neighbors=3)))
models.append(('knn5', KNeighborsClassifier(n_neighbors=5)))
models.append(('knn7', KNeighborsClassifier(n_neighbors=7)))
models.append(('knn9', KNeighborsClassifier(n_neighbors=9)))
# define the hard voting ensemble
ensemble = VotingClassifier(estimators=models, voting='hard')
# fit the model on all available data
ensemble.fit(X, y)
# make a prediction for one example
data = [[5.88891819,2.64867662,-0.42728226,-1.24988856,-0.00822,-3.57895574,2.87938412,-1.55614691,-0.38168784,7.50285659,-1.16710354,-5.02492712,-0.46196105,-0.64539455,-1.71297469,0.25987852,-0.193401,-5.52022952,0.0364453,-1.960039]]
yhat = ensemble.predict(data)
print('Predicted Class: %d' % (yhat))
运行该示例使硬投票集成模型适合整个数据集,然后用于对新的数据行进行预测,就像我们在应用程序中使用该模型时可能做的那样。
Predicted Class: 1
用于分类的软投票集成
我们可以用支持向量机 (SVM)算法来演示软投票。
SVM 算法本身并不预测概率,尽管它可以被配置为通过在 SVC 类中将“概率”参数设置为“真”来预测类似概率的分数。
我们可以用一个多项式核来拟合五个不同版本的 SVM 算法,每个核具有不同的多项式次数,通过“度参数来设置。我们将使用 1-5 度。
我们的期望是,通过组合由每个不同的 SVM 模型预测的预测类别成员概率分数,平均而言,软投票集成将获得比集成中使用的任何独立模型更好的预测表现。
首先,我们可以创建一个名为 get_voting() 的函数来创建 SVM 模型,并将它们组合成一个软投票集合。
# get a voting ensemble of models
def get_voting():
# define the base models
models = list()
models.append(('svm1', SVC(probability=True, kernel='poly', degree=1)))
models.append(('svm2', SVC(probability=True, kernel='poly', degree=2)))
models.append(('svm3', SVC(probability=True, kernel='poly', degree=3)))
models.append(('svm4', SVC(probability=True, kernel='poly', degree=4)))
models.append(('svm5', SVC(probability=True, kernel='poly', degree=5)))
# define the voting ensemble
ensemble = VotingClassifier(estimators=models, voting='soft')
return ensemble
然后,我们可以创建一个要评估的模型列表,包括每个独立版本的 SVM 模型配置和软投票集合。
这将有助于我们在分类准确率分数的分布方面直接比较 SVM 模型和集合的每个独立配置。下面的 get_models() 函数创建模型列表供我们评估。
# get a list of models to evaluate
def get_models():
models = dict()
models['svm1'] = SVC(probability=True, kernel='poly', degree=1)
models['svm2'] = SVC(probability=True, kernel='poly', degree=2)
models['svm3'] = SVC(probability=True, kernel='poly', degree=3)
models['svm4'] = SVC(probability=True, kernel='poly', degree=4)
models['svm5'] = SVC(probability=True, kernel='poly', degree=5)
models['soft_voting'] = get_voting()
return models
我们可以使用重复的 k-fold 交叉验证来评估和报告模型表现,就像我们在上一节中所做的那样。
将这些联系在一起,完整的示例如下所示。
# compare soft voting ensemble to standalone classifiers
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.svm import SVC
from sklearn.ensemble import VotingClassifier
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=2)
return X, y
# get a voting ensemble of models
def get_voting():
# define the base models
models = list()
models.append(('svm1', SVC(probability=True, kernel='poly', degree=1)))
models.append(('svm2', SVC(probability=True, kernel='poly', degree=2)))
models.append(('svm3', SVC(probability=True, kernel='poly', degree=3)))
models.append(('svm4', SVC(probability=True, kernel='poly', degree=4)))
models.append(('svm5', SVC(probability=True, kernel='poly', degree=5)))
# define the voting ensemble
ensemble = VotingClassifier(estimators=models, voting='soft')
return ensemble
# get a list of models to evaluate
def get_models():
models = dict()
models['svm1'] = SVC(probability=True, kernel='poly', degree=1)
models['svm2'] = SVC(probability=True, kernel='poly', degree=2)
models['svm3'] = SVC(probability=True, kernel='poly', degree=3)
models['svm4'] = SVC(probability=True, kernel='poly', degree=4)
models['svm5'] = SVC(probability=True, kernel='poly', degree=5)
models['soft_voting'] = get_voting()
return models
# evaluate a give model using cross-validation
def evaluate_model(model, X, y):
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
scores = evaluate_model(model, X, y)
results.append(scores)
names.append(name)
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行该示例首先报告每个模型的平均值和标准偏差准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
我们可以看到,与模型的所有独立版本相比,软投票集成实现了约 92.4%的更好的分类准确率。
>svm1 0.855 (0.035)
>svm2 0.859 (0.034)
>svm3 0.890 (0.035)
>svm4 0.808 (0.037)
>svm5 0.850 (0.037)
>soft_voting 0.924 (0.028)
然后创建一个方块-触须图,比较每个模型的分布准确率分数,使我们能够清楚地看到软投票集合的平均表现优于所有独立模型。
二进制分类的软投票集成与独立模型的箱图比较
如果我们选择一个软投票集合作为我们的最终模型,我们可以像任何其他模型一样,拟合并使用它来对新数据进行预测。
首先,软投票集成适用于所有可用数据,然后可以调用 predict() 函数对新数据进行预测。
下面的示例在我们的二进制类别数据集上演示了这一点。
# make a prediction with a soft voting ensemble
from sklearn.datasets import make_classification
from sklearn.ensemble import VotingClassifier
from sklearn.svm import SVC
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=2)
# define the base models
models = list()
models.append(('svm1', SVC(probability=True, kernel='poly', degree=1)))
models.append(('svm2', SVC(probability=True, kernel='poly', degree=2)))
models.append(('svm3', SVC(probability=True, kernel='poly', degree=3)))
models.append(('svm4', SVC(probability=True, kernel='poly', degree=4)))
models.append(('svm5', SVC(probability=True, kernel='poly', degree=5)))
# define the soft voting ensemble
ensemble = VotingClassifier(estimators=models, voting='soft')
# fit the model on all available data
ensemble.fit(X, y)
# make a prediction for one example
data = [[5.88891819,2.64867662,-0.42728226,-1.24988856,-0.00822,-3.57895574,2.87938412,-1.55614691,-0.38168784,7.50285659,-1.16710354,-5.02492712,-0.46196105,-0.64539455,-1.71297469,0.25987852,-0.193401,-5.52022952,0.0364453,-1.960039]]
yhat = ensemble.predict(data)
print('Predicted Class: %d' % (yhat))
运行该示例使软投票集成模型适合整个数据集,然后用于对新的数据行进行预测,就像我们在应用程序中使用该模型时可能做的那样。
Predicted Class: 1
回归投票集成
在这一节中,我们将研究使用投票来解决回归问题。
首先,我们可以使用make _ revolution()函数创建一个包含 1000 个示例和 20 个输入特征的合成回归问题。
下面列出了完整的示例。
# test regression dataset
from sklearn.datasets import make_regression
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=1)
# summarize the dataset
print(X.shape, y.shape)
运行该示例将创建数据集并总结输入和输出组件的形状。
(1000, 20) (1000,)
我们可以用决策树算法演示回归的集成投票,有时称为分类和回归树 (CART)算法。
我们可以拟合 CART 算法的五个不同版本,每个版本都有不同的决策树最大深度,通过“ max_depth ”参数设置。我们将使用 1-5 的深度。
我们的期望是,通过组合由每个不同的 CART 模型预测的值,平均而言,投票集成将获得比集成中使用的任何独立模型更好的预测表现。
首先,我们可以创建一个名为 get_voting() 的函数,该函数创建每个 CART 模型并将这些模型组合成一个投票集合。
# get a voting ensemble of models
def get_voting():
# define the base models
models = list()
models.append(('cart1', DecisionTreeRegressor(max_depth=1)))
models.append(('cart2', DecisionTreeRegressor(max_depth=2)))
models.append(('cart3', DecisionTreeRegressor(max_depth=3)))
models.append(('cart4', DecisionTreeRegressor(max_depth=4)))
models.append(('cart5', DecisionTreeRegressor(max_depth=5)))
# define the voting ensemble
ensemble = VotingRegressor(estimators=models)
return ensemble
然后,我们可以创建一个要评估的模型列表,包括 CART 模型配置的每个独立版本和软投票集合。
这将有助于我们直接比较 CART 模型的每个独立配置和错误分数分布的集合。下面的 get_models() 函数创建模型列表供我们评估。
# get a list of models to evaluate
def get_models():
models = dict()
models['cart1'] = DecisionTreeRegressor(max_depth=1)
models['cart2'] = DecisionTreeRegressor(max_depth=2)
models['cart3'] = DecisionTreeRegressor(max_depth=3)
models['cart4'] = DecisionTreeRegressor(max_depth=4)
models['cart5'] = DecisionTreeRegressor(max_depth=5)
models['voting'] = get_voting()
return models
我们可以使用重复的 k 倍交叉验证来评估和报告模型表现,就像我们在上一节中所做的那样。
使用平均绝对误差(MAE)评估模型。Sklearn 将分数设为负值,这样可以最大化分数。这意味着报告的 MAE 分数为负,数值越大越好,0 表示没有误差。
将这些联系在一起,完整的示例如下所示。
# compare voting ensemble to each standalone models for regression
from numpy import mean
from numpy import std
from sklearn.datasets import make_regression
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedKFold
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import VotingRegressor
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=1)
return X, y
# get a voting ensemble of models
def get_voting():
# define the base models
models = list()
models.append(('cart1', DecisionTreeRegressor(max_depth=1)))
models.append(('cart2', DecisionTreeRegressor(max_depth=2)))
models.append(('cart3', DecisionTreeRegressor(max_depth=3)))
models.append(('cart4', DecisionTreeRegressor(max_depth=4)))
models.append(('cart5', DecisionTreeRegressor(max_depth=5)))
# define the voting ensemble
ensemble = VotingRegressor(estimators=models)
return ensemble
# get a list of models to evaluate
def get_models():
models = dict()
models['cart1'] = DecisionTreeRegressor(max_depth=1)
models['cart2'] = DecisionTreeRegressor(max_depth=2)
models['cart3'] = DecisionTreeRegressor(max_depth=3)
models['cart4'] = DecisionTreeRegressor(max_depth=4)
models['cart5'] = DecisionTreeRegressor(max_depth=5)
models['voting'] = get_voting()
return models
# evaluate a give model using cross-validation
def evaluate_model(model, X, y):
cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)
scores = cross_val_score(model, X, y, scoring='neg_mean_absolute_error', cv=cv, n_jobs=-1, error_score='raise')
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
scores = evaluate_model(model, X, y)
results.append(scores)
names.append(name)
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行该示例首先报告每个模型的平均值和标准偏差准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
我们可以看到,投票集成实现了更好的均方误差,约为-136.338,与模型的所有独立版本相比,这更大(更好)。
>cart1 -161.519 (11.414)
>cart2 -152.596 (11.271)
>cart3 -142.378 (10.900)
>cart4 -140.086 (12.469)
>cart5 -137.641 (12.240)
>voting -136.338 (11.242)
然后创建一个方框图,比较每个模型的负 MAE 分数分布,让我们清楚地看到,平均而言,投票集合比所有独立模型表现更好。
投票集合与独立回归模型的箱线图比较
如果我们选择一个投票集合作为我们的最终模型,我们可以像任何其他模型一样,拟合并使用它来对新数据进行预测。
首先,投票集合适合所有可用数据,然后可以调用 predict() 函数对新数据进行预测。
下面的示例在我们的二进制类别数据集上演示了这一点。
# make a prediction with a voting ensemble
from sklearn.datasets import make_regression
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import VotingRegressor
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=1)
# define the base models
models = list()
models.append(('cart1', DecisionTreeRegressor(max_depth=1)))
models.append(('cart2', DecisionTreeRegressor(max_depth=2)))
models.append(('cart3', DecisionTreeRegressor(max_depth=3)))
models.append(('cart4', DecisionTreeRegressor(max_depth=4)))
models.append(('cart5', DecisionTreeRegressor(max_depth=5)))
# define the voting ensemble
ensemble = VotingRegressor(estimators=models)
# fit the model on all available data
ensemble.fit(X, y)
# make a prediction for one example
data = [[0.59332206,-0.56637507,1.34808718,-0.57054047,-0.72480487,1.05648449,0.77744852,0.07361796,0.88398267,2.02843157,1.01902732,0.11227799,0.94218853,0.26741783,0.91458143,-0.72759572,1.08842814,-0.61450942,-0.69387293,1.69169009]]
yhat = ensemble.predict(data)
print('Predicted Value: %.3f' % (yhat))
运行该示例使投票集成模型适合整个数据集,然后用于对新的数据行进行预测,就像我们在应用程序中使用该模型时可能做的那样。
Predicted Value: 141.319
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
教程
书
- 数据挖掘:实用机器学习工具与技术,2016。
蜜蜂
摘要
在本教程中,您发现了如何在 Python 中为机器学习算法创建投票集成。
具体来说,您了解到:
- 投票集合包括对分类模型做出的预测进行求和,或者对回归模型做出的预测进行平均。
- 投票组合是如何工作的,何时使用投票组合,以及该方法的局限性。
- 如何实现用于分类预测建模的硬投票集成和软投票集成?
你有什么问题吗? 在下面的评论中提问,我会尽力回答。