加权平均集成假设集成中的某些模型比其他模型更具能力,并在进行预测时给予它们更多的贡献。
加权平均或加权求和集成是投票集成的扩展,投票集成假设所有模型都同样有能力,并对集成做出的预测做出相同的比例贡献。
每个模型都被赋予一个固定权重,该权重乘以模型做出的预测,并用于求和或平均预测计算。这种集成的挑战是如何计算、分配或搜索模型权重,以使其性能优于任何贡献模型以及使用相等模型权重的集成。
在本教程中,您将学习如何为分类和回归开发加权平均集成。
完成本教程后,您将了解:
- 加权平均集成是投票集成的扩展,其中模型的投票与模型性能成比例。
- 如何使用 scikit-learn 中的投票集成来开发加权平均集成。
- 如何评估用于分类和回归的加权平均集成,并确认模型有能力。
通过我的新书《使用 Python 的集成学习算法》启动您的项目,包括分步教程和所有示例的 Python 源代码文件。
让我们开始吧。
- 2021年5月更新:修正了加权平均的定义。

如何使用 Python 开发加权平均集成
图片由Alaina McDavid提供,保留部分权利。
教程概述
本教程分为四个部分;它们是
- 加权平均集成
- 开发加权平均集成
- 用于分类的加权平均集成
- 用于回归的加权平均集成
加权平均集成
加权平均或加权求和集成是一种集成机器学习方法,它结合了多个模型的预测,其中每个模型的贡献与其能力或技能成比例地加权。
加权平均集成与投票集成相关。
投票集成由多个机器学习模型组成,其中每个模型的预测直接平均。对于回归,这涉及计算集成成员预测的算术平均值。对于分类,这可能涉及计算统计众数(最常见的类别标签)或类似的投票方案,或者将每个类别的预测概率相加并选择总和概率最大的类别。
有关投票集成的更多信息,请参阅教程
投票集成技术的一个局限性在于它假定集成中的所有模型都同样有效。情况可能并非如此,因为某些模型可能比其他模型更好,特别是如果使用不同的机器学习算法来训练每个模型集成成员。
投票的替代方案是假设集成成员并非都同样有能力,而是某些模型比其他模型更好,并且在进行预测时应给予更多的票数或更大的权重。这为加权求和或加权平均集成方法提供了动力。
在回归中,平均预测是使用算术平均值计算的,例如预测的总和除以所做的总预测数。例如,如果一个集成有三个集成成员,那么它们可能是
- 模型 1: 97.2
- 模型 2: 100.0
- 模型 3: 95.8
平均预测将按如下方式计算
- yhat = (97.2 + 100.0 + 95.8) / 3
- yhat = 293 / 3
- yhat = 97.666
加权平均预测首先为每个集成成员分配一个固定权重系数。这可以是一个介于 0 和 1 之间的浮点值,表示权重的百分比。它也可以是一个从 1 开始的整数,表示每个模型要给予的票数。
例如,我们可能为集成成员设置固定权重为 0.84、0.87、0.75。这些权重可以通过将每个预测乘以模型的权重来计算加权平均值,从而得到加权和,然后将该值除以权重的总和。例如
- yhat = ((97.2 * 0.84) + (100.0 * 0.87) + (95.8 * 0.75)) / (0.84 + 0.87 + 0.75)
- yhat = (81.648 + 87 + 71.85) / (0.84 + 0.87 + 0.75)
- yhat = 240.498 / 2.46
- yhat = 97.763
我们可以看到,只要分数具有相同的刻度,并且权重具有相同的刻度并且最大化(意味着较大的权重更好),加权和就会产生一个合理的值,反过来,加权平均值也是合理的,这意味着结果的刻度与分数的刻度匹配。
同样的方法可以用于计算每个清晰类别标签的加权投票和,或分类问题中每个类别标签的加权概率和。
使用加权平均集成具有挑战性的一方面是如何为每个集成成员选择相对权重。
有许多方法可以使用。例如,权重可以根据每个模型的技能来选择,例如分类准确率或负误差,其中较大的权重意味着性能更好的模型。性能可以在用于训练的数据集上计算,也可以在保留数据集上计算,后者可能更相关。
每个模型的分数可以直接使用,也可以转换为不同的值,例如每个模型的相对排名。另一种方法可能是使用搜索算法来测试不同的权重组合。
现在我们熟悉了加权平均集成方法,让我们看看如何开发和评估它们。
想开始学习集成学习吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
开发加权平均集成
在本节中,我们将开发、评估和使用加权平均或加权求和集成模型。
我们可以手动实现加权平均集成,尽管这并非必需,因为我们可以使用 scikit-learn 库中的投票集成来实现所需的效果。具体来说,VotingRegressor 和 VotingClassifier 类可分别用于回归和分类,两者都提供了一个“weights”参数,用于指定每个集成成员在进行预测时的相对贡献。
通过“estimators”参数提供一个基模型列表。这是一个 Python 列表,其中列表中的每个元素都是一个元组,包含模型的名称和配置的模型实例。列表中的每个模型必须具有唯一的名称。
例如,我们可以定义一个具有两个集成成员的分类加权平均集成,如下所示
1 2 3 4 5 6 7 |
... # 定义集成中的模型 models = [('lr',LogisticRegression()),('svm',SVC())] # 定义集成中每个模型的权重 weights = [0.7, 0.9] # 创建加权求和集成 ensemble = VotingClassifier(estimators=models, weights=weights) |
此外,用于分类的投票集成提供了“voting”参数,该参数支持“硬投票”('hard')用于组合清晰的类别标签和“软投票”('soft')用于在计算预测的加权和时组合类别概率;例如
1 2 3 4 5 6 7 |
... # 定义集成中的模型 models = [('lr',LogisticRegression()),('svm',SVC())] # 定义集成中每个模型的权重 weights = [0.7, 0.9] # 创建加权求和集成 ensemble = VotingClassifier(estimators=models, weights=weights, voting='soft') |
如果贡献模型支持预测类别概率,通常首选软投票,因为它通常会带来更好的性能。这对于预测概率的加权和也是如此。
现在我们熟悉了如何使用投票集成 API 来开发加权平均集成,让我们看一些实际示例。
用于分类的加权平均集成
在本节中,我们将探讨在分类问题中使用加权平均集成。
首先,我们可以使用 make_classification() 函数创建一个具有 10,000 个示例和 20 个输入特征的合成二元分类问题。
完整的示例如下所示。
1 2 3 4 5 6 |
# 测试分类数据集 from sklearn.datasets import make_classification # 定义数据集 X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5, random_state=7) # 汇总数据集 print(X.shape, y.shape) |
运行示例会创建数据集并总结输入和输出组件的形状。
1 |
(10000, 20) (10000,) |
接下来,我们可以在这个数据集上评估一个加权平均集成算法。
首先,我们将数据集以 50-50 的比例分成训练集和测试集。然后,我们将完整的训练集分成用于训练模型的子集和用于验证的子集。
1 2 3 4 5 |
... # 将数据集分割为训练集和测试集 X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.50, random_state=1) # 将完整的训练集分成训练集和验证集 X_train, X_val, y_train, y_val = train_test_split(X_train_full, y_train_full, test_size=0.33, random_state=1) |
接下来,我们将定义一个函数来创建集成中使用的模型列表。在这种情况下,我们将使用一系列不同的分类模型,包括逻辑回归、决策树和朴素贝叶斯。
1 2 3 4 5 6 7 |
# 获取基模型列表 定义 获取_模型(): models = list() models.append(('lr', LogisticRegression())) models.append(('cart', DecisionTreeClassifier())) models.append(('bayes', GaussianNB())) 返回 models |
接下来,我们需要给每个集成成员加权。
在这种情况下,我们将使用每个集成模型在训练数据集上的性能作为模型在进行预测时的相对权重。性能将使用分类准确率计算,表示正确预测的百分比,介于 0 到 1 之间,值越大表示模型越好,从而对预测的贡献越大。
每个集成模型将首先在训练集上拟合,然后在验证集上进行评估。验证集上的准确率将用作模型权重。
下面的 evaluate_models() 函数实现了这一点,返回每个模型的性能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 评估每个基模型 def evaluate_models(models, X_train, X_val, y_train, y_val): # 拟合和评估模型 scores = list() for name, model in models: # 拟合模型 model.fit(X_train, y_train) # 评估模型 yhat = model.predict(X_val) acc = accuracy_score(y_val, yhat) # 存储性能 scores.append(acc) # 报告模型性能 return scores |
然后我们可以调用此函数来获取分数,并将其用作集成的权重。
1 2 3 4 5 |
... # 拟合和评估每个模型 scores = evaluate_models(models, X_train, X_val, y_train, y_val) # 创建集成 ensemble = VotingClassifier(estimators=models, voting='soft', weights=scores) |
然后我们可以在完整的训练数据集上拟合集成,并在保留测试集上对其进行评估。
1 2 3 4 5 6 7 8 |
... # 在训练数据集上拟合集成 ensemble.fit(X_train, y_train) # 对测试集进行预测 yhat = ensemble.predict(X_test) # 评估预测 score = accuracy_score(y_test, yhat) print('Weighted Avg Accuracy: %.3f' % (score*100)) |
将这些结合起来,完整的示例列在下面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# 评估分类的加权平均集成 from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from sklearn.linear_model import LogisticRegression from sklearn.tree import DecisionTreeClassifier from sklearn.naive_bayes import GaussianNB from sklearn.ensemble import VotingClassifier # 获取基模型列表 定义 获取_模型(): models = list() models.append(('lr', LogisticRegression())) models.append(('cart', DecisionTreeClassifier())) models.append(('bayes', GaussianNB())) 返回 模型 # 评估每个基模型 def evaluate_models(models, X_train, X_val, y_train, y_val): # 拟合和评估模型 scores = list() for name, model in models: # 拟合模型 model.fit(X_train, y_train) # 评估模型 yhat = model.predict(X_val) acc = accuracy_score(y_val, yhat) # 存储性能 scores.append(acc) # 报告模型性能 返回 分数 # 定义数据集 X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5, random_state=7) # 将数据集分割为训练集和测试集 X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.50, random_state=1) # 将完整的训练集分成训练集和验证集 X_train, X_val, y_train, y_val = train_test_split(X_train_full, y_train_full, test_size=0.33, random_state=1) # 创建基模型 模型 = 获取_模型() # 拟合和评估每个模型 scores = evaluate_models(models, X_train, X_val, y_train, y_val) print(scores) # 创建集成 ensemble = VotingClassifier(estimators=models, voting='soft', weights=scores) # 在训练数据集上拟合集成 ensemble.fit(X_train_full, y_train_full) # 对测试集进行预测 yhat = ensemble.predict(X_test) # 评估预测 score = accuracy_score(y_test, yhat) print('Weighted Avg Accuracy: %.3f' % (score*100)) |
运行该示例首先评估每个独立模型并报告将用作模型权重的准确率分数。最后,拟合加权平均集成并在测试集上进行评估,报告其性能。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。考虑多次运行示例并比较平均结果。
在这种情况下,我们可以看到投票集成实现了约 90.960% 的分类准确率。
1 2 |
[0.8896969696969697, 0.8575757575757575, 0.8812121212121212] 加权平均准确率:90.960 |
我们期望集成模型的性能优于任何单个贡献模型。问题在于用于加权的模型准确率分数不能直接与集成模型的性能进行比较,因为集成模型是在训练子集上评估的,而集成模型是在测试数据集上评估的。
我们可以更新示例并添加每个独立模型的评估以进行比较。
1 2 3 4 5 |
... # 评估每个独立模型 scores = evaluate_models(models, X_train_full, X_test, y_train_full, y_test) for i in range(len(models)): print('>%s: %.3f' % (models[i][0], scores[i]*100)) |
我们还期望加权平均集成模型的性能优于等权重的投票集成模型。
这也可以通过明确评估投票集成来检查。
1 2 3 4 5 6 7 |
... # 评估等权重 ensemble = VotingClassifier(estimators=models, voting='soft') ensemble.fit(X_train_full, y_train_full) yhat = ensemble.predict(X_test) score = accuracy_score(y_test, yhat) print('Voting Accuracy: %.3f' % (score*100)) |
将这些结合起来,完整的示例列在下面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# 评估分类的加权平均集成与基模型的比较 from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from sklearn.linear_model import LogisticRegression from sklearn.tree import DecisionTreeClassifier from sklearn.naive_bayes import GaussianNB from sklearn.ensemble import VotingClassifier # 获取基模型列表 定义 获取_模型(): models = list() models.append(('lr', LogisticRegression())) models.append(('cart', DecisionTreeClassifier())) models.append(('bayes', GaussianNB())) 返回 模型 # 评估每个基模型 def evaluate_models(models, X_train, X_val, y_train, y_val): # 拟合和评估模型 scores = list() for name, model in models: # 拟合模型 model.fit(X_train, y_train) # 评估模型 yhat = model.predict(X_val) acc = accuracy_score(y_val, yhat) # 存储性能 scores.append(acc) # 报告模型性能 返回 分数 # 定义数据集 X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5, random_state=7) # 将数据集分割为训练集和测试集 X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.50, random_state=1) # 将完整的训练集分成训练集和验证集 X_train, X_val, y_train, y_val = train_test_split(X_train_full, y_train_full, test_size=0.33, random_state=1) # 创建基模型 模型 = 获取_模型() # 拟合和评估每个模型 scores = evaluate_models(models, X_train, X_val, y_train, y_val) print(scores) # 创建集成 ensemble = VotingClassifier(estimators=models, voting='soft', weights=scores) # 在训练数据集上拟合集成 ensemble.fit(X_train_full, y_train_full) # 对测试集进行预测 yhat = ensemble.predict(X_test) # 评估预测 score = accuracy_score(y_test, yhat) print('Weighted Avg Accuracy: %.3f' % (score*100)) # 评估每个独立模型 scores = evaluate_models(models, X_train_full, X_test, y_train_full, y_test) for i in range(len(models)): print('>%s: %.3f' % (models[i][0], scores[i]*100)) # 评估等权重 ensemble = VotingClassifier(estimators=models, voting='soft') ensemble.fit(X_train_full, y_train_full) yhat = ensemble.predict(X_test) score = accuracy_score(y_test, yhat) print('Voting Accuracy: %.3f' % (score*100)) |
运行该示例首先像之前一样准备和评估加权平均集成,然后报告每个单独评估的贡献模型的性能,最后是使用相等模型权重的投票集成的性能。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。考虑多次运行示例并比较平均结果。
在这种情况下,我们可以看到加权平均集成的性能优于任何贡献的集成成员。
我们还可以看到,等权重集成(投票)的准确率约为 90.620%,低于加权集成实现的略高 90.760% 的准确率。
1 2 3 4 5 6 |
[0.8896969696969697, 0.8703030303030304, 0.8812121212121212] 加权平均准确率:90.760 >lr: 87.800 >cart: 88.180 >bayes: 87.300 投票准确率:90.620 |
接下来,让我们看看如何开发和评估用于回归的加权平均集成。
用于回归的加权平均集成
在本节中,我们将探讨在回归问题中使用加权平均集成。
首先,我们可以使用 make_regression() 函数 创建一个包含 1,000 个示例和 20 个输入特征的合成回归问题。
完整的示例如下所示。
1 2 3 4 5 6 |
# 测试回归数据集 from sklearn.datasets import make_regression # 定义数据集 X, y = make_regression(n_samples=10000, n_features=20, n_informative=10, noise=0.3, random_state=7) # 汇总数据集 print(X.shape, y.shape) |
运行示例会创建数据集并总结输入和输出组件的形状。
1 |
(10000, 20) (10000,) |
接下来,我们可以在这个数据集上评估一个加权平均集成模型。
首先,我们可以将数据集分成训练集和测试集,然后进一步将训练集分成训练集和验证集,以便我们可以估计每个贡献模型的性能。
1 2 3 4 5 |
... # 将数据集分割为训练集和测试集 X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.50, random_state=1) # 将完整的训练集分成训练集和验证集 X_train, X_val, y_train, y_val = train_test_split(X_train_full, y_train_full, test_size=0.33, random_state=1) |
我们可以定义集成中使用的模型列表。在这种情况下,我们将使用 k-近邻、决策树和支持向量回归。
1 2 3 4 5 6 7 |
# 获取基模型列表 定义 获取_模型(): models = list() models.append(('knn', KNeighborsRegressor())) models.append(('cart', DecisionTreeRegressor())) models.append(('svm', SVR())) 返回 models |
接下来,我们可以更新 evaluate_models() 函数,以计算每个集成成员在保留验证数据集上的平均绝对误差 (MAE)。
我们将使用负 MAE 分数作为权重,其中接近零的较大误差值表示性能更好的模型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 评估每个基模型 def evaluate_models(models, X_train, X_val, y_train, y_val): # 拟合和评估模型 scores = list() for name, model in models: # 拟合模型 model.fit(X_train, y_train) # 评估模型 yhat = model.predict(X_val) mae = mean_absolute_error(y_val, yhat) # 存储性能 scores.append(-mae) # 报告模型性能 return scores |
然后我们可以调用此函数来获取分数,并用它们来定义用于回归的加权平均集成。
1 2 3 4 5 6 |
... # 拟合和评估每个模型 scores = evaluate_models(models, X_train, X_val, y_train, y_val) print(scores) # 创建集成 ensemble = VotingRegressor(estimators=models, weights=scores) |
然后我们可以在整个训练数据集上拟合集成,并评估其在保留测试数据集上的性能。
1 2 3 4 5 6 7 8 |
... # 在训练数据集上拟合集成 ensemble.fit(X_train_full, y_train_full) # 对测试集进行预测 yhat = ensemble.predict(X_test) # 评估预测 score = mean_absolute_error(y_test, yhat) print('Weighted Avg MAE: %.3f' % (score)) |
我们期望集成模型的性能优于任何单个贡献集成成员,这可以通过在完整的训练集和测试集上独立评估每个成员模型来直接检查。
1 2 3 4 5 |
... # 评估每个独立模型 scores = evaluate_models(models, X_train_full, X_test, y_train_full, y_test) for i in range(len(models)): print('>%s: %.3f' % (models[i][0], scores[i])) |
最后,我们还期望加权平均集成的性能优于相同集成且采用等权重的情况。这一点也可以得到证实。
1 2 3 4 5 6 7 |
... # 评估等权重 ensemble = VotingRegressor(estimators=models) ensemble.fit(X_train_full, y_train_full) yhat = ensemble.predict(X_test) score = mean_absolute_error(y_test, yhat) print('Voting MAE: %.3f' % (score)) |
综合起来,下面列出了评估回归加权平均集成的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# 评估回归的加权平均集成 from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.metrics import mean_absolute_error from sklearn.neighbors import KNeighborsRegressor 来自 sklearn.tree 导入 DecisionTreeRegressor 来自 sklearn.svm 导入 SVR from sklearn.ensemble import VotingRegressor # 获取基模型列表 定义 获取_模型(): models = list() models.append(('knn', KNeighborsRegressor())) models.append(('cart', DecisionTreeRegressor())) models.append(('svm', SVR())) 返回 模型 # 评估每个基模型 def evaluate_models(models, X_train, X_val, y_train, y_val): # 拟合和评估模型 scores = list() for name, model in models: # 拟合模型 model.fit(X_train, y_train) # 评估模型 yhat = model.predict(X_val) mae = mean_absolute_error(y_val, yhat) # 存储性能 scores.append(-mae) # 报告模型性能 返回 分数 # 定义数据集 X, y = make_regression(n_samples=10000, n_features=20, n_informative=10, noise=0.3, random_state=7) # 将数据集分割为训练集和测试集 X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.50, random_state=1) # 将完整的训练集分成训练集和验证集 X_train, X_val, y_train, y_val = train_test_split(X_train_full, y_train_full, test_size=0.33, random_state=1) # 创建基模型 模型 = 获取_模型() # 拟合和评估每个模型 scores = evaluate_models(models, X_train, X_val, y_train, y_val) print(scores) # 创建集成 ensemble = VotingRegressor(estimators=models, weights=scores) # 在训练数据集上拟合集成 ensemble.fit(X_train_full, y_train_full) # 对测试集进行预测 yhat = ensemble.predict(X_test) # 评估预测 score = mean_absolute_error(y_test, yhat) print('Weighted Avg MAE: %.3f' % (score)) # 评估每个独立模型 scores = evaluate_models(models, X_train_full, X_test, y_train_full, y_test) for i in range(len(models)): print('>%s: %.3f' % (models[i][0], scores[i])) # 评估等权重 ensemble = VotingRegressor(estimators=models) ensemble.fit(X_train_full, y_train_full) yhat = ensemble.predict(X_test) score = mean_absolute_error(y_test, yhat) print('Voting MAE: %.3f' % (score)) |
运行该示例首先报告每个集成成员的负 MAE,该值将用作分数,然后是加权平均集成的性能。最后,报告每个独立模型的性能以及等权重集成的性能。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。考虑多次运行示例并比较平均结果。
在这种情况下,我们可以看到加权平均集成实现了约 105.158 的平均绝对误差,这比单独的 kNN 模型(误差约为 100.169)更差(误差更大)。我们还可以看到,假设每个模型权重相等的投票集成也比加权平均集成表现更好,误差约为 102.706。
1 2 3 4 5 6 |
[-101.97000126284476, -142.26014983127837, -153.9765827528269] 加权平均 MAE:105.158 >knn: -100.169 >cart: -134.487 >svm: -138.195 投票 MAE:102.706 |
加权平均集成的性能低于预期,这可能与模型加权方式的选择有关。
另一种加权策略是使用排名来指示每个集成在加权平均中的投票数量。
例如,在三个集成成员的情况下,表现最差的模型有 1 票,次差的有 2 票,最好的模型有 3 票。
这可以通过使用 argsort() numpy 函数来实现。
argsort 函数返回数组中值如果被排序后的索引。因此,如果我们有数组 [300, 100, 200],最小值的索引是 1,次大值的索引是 2,最大值的索引是 0。
因此,[300, 100, 200] 的 argsort 是 [1, 2, 0]。
然后我们可以对 argsort 的结果进行 argsort,以给出原始数组中数据的排名。要了解其原理,[1, 2, 0] 的 argsort 将表明索引 2 是最小值,其次是索引 0,最后是索引 1。
因此,[1, 2, 0] 的 argsort 是 [2, 0, 1]。换句话说,[300, 100, 200] 的 argsort 的 argsort 是 [2, 0, 1],这是数组中每个值如果按升序排序后的相对排名。也就是说
- 300:排名为 2
- 100:排名为 0
- 200:排名为 1
我们可以通过下面的一个小例子来阐明这一点。
1 2 3 4 5 6 7 8 9 |
# 演示 argsort from numpy import argsort # 数据 x = [300, 100, 200] print(x) # 数据的 argsort print(argsort(x)) # 数据的 argsort 的 argsort print(argsort(argsort(x))) |
运行该示例首先报告原始数据,然后是原始数据的 argsort,以及原始数据的 argsort 的 argsort。
结果与我们手动计算的相符。
1 2 3 |
[300, 100, 200] [1 2 0] [2 0 1] |
我们可以使用模型分数的 argsort 的 argsort 来计算每个集成成员的相对排名。如果负平均绝对误差按升序排序,那么最佳模型将具有最大的负误差,进而具有最高的排名。表现最差的模型将具有最小的负误差,进而具有最低的排名。
再次,我们可以通过一个实际的例子来证实这一点。
1 2 3 4 5 6 7 8 9 |
# 演示带负分数的 argsort from numpy import argsort # 数据 x = [-10, -100, -80] print(x) # 数据的 argsort print(argsort(x)) # 数据的 argsort 的 argsort print(argsort(argsort(x))) |
运行示例,我们可以看到第一个模型得分最好(-10),第二个模型得分最差(-100)。
分数的 argsort 的 argsort 显示,最佳模型获得最高排名(最多投票),值为 2;最差模型获得最低排名(最少投票),值为 0。
1 2 3 |
[-10, -100, -80] [1 2 0] [2 0 1] |
在实践中,我们不希望任何模型有零票,因为它将被排除在集成之外。因此,我们可以将所有排名加 1。
计算出分数后,我们可以对模型分数的 argsort 进行 argsort,从而得到排名。然后使用模型排名作为加权平均集成的模型权重。
1 2 3 4 5 6 7 8 |
... # 拟合和评估每个模型 scores = evaluate_models(models, X_train, X_val, y_train, y_val) print(scores) ranking = 1 + argsort(argsort(scores)) print(ranking) # 创建集成 ensemble = VotingRegressor(estimators=models, weights=ranking) |
综合起来,下面列出了使用模型排名作为模型权重的回归加权平均集成的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# 评估使用模型排名作为模型权重的回归加权平均集成 from numpy import argsort from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.metrics import mean_absolute_error from sklearn.neighbors import KNeighborsRegressor 来自 sklearn.tree 导入 DecisionTreeRegressor 来自 sklearn.svm 导入 SVR from sklearn.ensemble import VotingRegressor # 获取基模型列表 定义 获取_模型(): models = list() models.append(('knn', KNeighborsRegressor())) models.append(('cart', DecisionTreeRegressor())) models.append(('svm', SVR())) 返回 模型 # 评估每个基模型 def evaluate_models(models, X_train, X_val, y_train, y_val): # 拟合和评估模型 scores = list() for name, model in models: # 拟合模型 model.fit(X_train, y_train) # 评估模型 yhat = model.predict(X_val) mae = mean_absolute_error(y_val, yhat) # 存储性能 scores.append(-mae) # 报告模型性能 返回 分数 # 定义数据集 X, y = make_regression(n_samples=10000, n_features=20, n_informative=10, noise=0.3, random_state=7) # 将数据集分割为训练集和测试集 X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.50, random_state=1) # 将完整的训练集分成训练集和验证集 X_train, X_val, y_train, y_val = train_test_split(X_train_full, y_train_full, test_size=0.33, random_state=1) # 创建基模型 模型 = 获取_模型() # 拟合和评估每个模型 scores = evaluate_models(models, X_train, X_val, y_train, y_val) print(scores) ranking = 1 + argsort(argsort(scores)) print(ranking) # 创建集成 ensemble = VotingRegressor(estimators=models, weights=ranking) # 在训练数据集上拟合集成 ensemble.fit(X_train_full, y_train_full) # 对测试集进行预测 yhat = ensemble.predict(X_test) # 评估预测 score = mean_absolute_error(y_test, yhat) print('Weighted Avg MAE: %.3f' % (score)) # 评估每个独立模型 scores = evaluate_models(models, X_train_full, X_test, y_train_full, y_test) for i in range(len(models)): print('>%s: %.3f' % (models[i][0], scores[i])) # 评估等权重 ensemble = VotingRegressor(estimators=models) ensemble.fit(X_train_full, y_train_full) yhat = ensemble.predict(X_test) score = mean_absolute_error(y_test, yhat) print('Voting MAE: %.3f' % (score)) |
运行该示例首先对每个模型进行评分,然后将分数转换为排名。然后评估使用排名的加权平均集成,并将其与每个独立模型的性能以及等权重集成进行比较。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。考虑多次运行示例并比较平均结果。
在这种情况下,我们可以看到排名如预期般进行,表现最好的成员 kNN 评分为 101,被分配了 3 级,其他模型也相应排名。我们可以看到加权平均集成实现了约 96.692 的 MAE,这优于任何单个模型和未加权的投票集成。
这突出了在集成中探索选择模型权重的替代方法的重要性。
1 2 3 4 5 6 7 |
[-101.97000126284476, -141.51998518020065, -153.9765827528269] [3 2 1] 加权平均 MAE:96.692 >knn: -100.169 >cart: -132.976 >svm: -138.195 投票 MAE:102.832 |
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
相关教程
API
文章
总结
在本教程中,您学习了如何为分类和回归开发加权平均集成。
具体来说,你学到了:
- 加权平均集成是投票集成的扩展,其中模型的投票与模型性能成比例。
- 如何使用 scikit-learn 中的投票集成来开发加权平均集成。
- 如何评估用于分类和回归的加权平均集成,并确认模型有能力。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
在你的加权平均例子中,你应该除以权重的总和。也就是说,这个例子
yhat = ((97.2 * 0.84) + (100.0 * 0.87) + (95.8 * 0.75)) / 3
yhat = (81.648 + 87 + 71.85) / 3
yhat = 240.498 / 3
yhat = 80.166
应该是
yhat = ((97.2 * 0.84) + (100.0 * 0.87) + (95.8 * 0.75)) / (0.84 + 0.87 + 0.75)
yhat = (81.648 + 87 + 71.85) / 2.46
yhat = 240.498 / 2.46
yhat = 97.763
你发布的(不正确)加权平均值显然是错误的,因为加权平均值应该介于被平均的最小值和最大值之间(值 80.166 不在区间 [95.8, 100] 内)
啊,是的,按权重的总和归一化。谢谢,已更正。
嗨,Jason博士,
这无论如何都是一篇写得很好的文章。感谢您为这项工作付出的时间和精力。
为什么 VotingRegressor 中每个贡献模型或成员的性能是用负 MAE 指标估计的?为什么我们不能使用 0 到 1 之间的分数来获取每个模型的权重?我不明白为什么 VotingRessor 排名方法中的加权平均 MAE: 96.692 会优于所有为负值的集成成员分数。我以为 MAE 越小,模型性能越好。
其次,是否可以将神经网络模型添加到集成中?我尝试使用 KerasRegressor() 方法这样做,但我遇到的一个错误是当我尝试使用估计器在保留数据集上进行预测时,“KerasRegressor”对象没有“模型”属性。
谢谢。
使用负 MAE 是有意为之的,来自帖子
是的,你可以使用神经网络。或许可以尝试 sklearn 的 MLPRegressor。
你好先生,
这里给出的加权机制是否可以用于超学习器?
也许可以尝试一下。
在“加权平均集成”部分,正确的数学加权平均公式告诉我们,
yhat = ((97.2 * 0.84) + (100.0 * 0.87) + (95.8 * 0.75)) / (0.84 + 0.87 + 0.75)
yhat = 97.76
谢谢,已修正。
嗨,Jason,
非常感谢这个教程。它使得入门变得非常容易。不过我有一个问题,关于单个模型的性能,例如
def get_models()
models = list()
models.append((‘lr’, LogisticRegression()))
models.append((‘cart’, DecisionTreeClassifier()))
models.append((‘bayes’, GaussianNB()))
你包含了使用默认超参数的模型。是否可以(“手动”)调整并首先确定每个分类器的超参数,然后将它们与那些表现最佳的超参数一起包含在列表中?我想这将是一个相当耗时的过程。你建议的工作流程中是否有智能的方法可以自动化这一点?
再次感谢,Jason!
奥利弗
好问题,是的,在将模型添加到集成之前稍微调整一下模型可能是一个好主意。不过不要调整太多,因为这会使模型变得脆弱,并使集成结果变差。
Jason博士您好,
我有三个问题
我有一个数据集,并对其实现了投票。(NB、SVM 和 MLP 的集成)。包括硬投票和软投票。结果显示 SVM 比投票更好。
第一个问题是为什么?投票不应该有更好的结果吗?
第二个是我没有定义权重。只写了硬投票和软投票。就这样。然而结果略有变化。我不明白为什么会发生这种情况。我以为如果我不定义权重,那么硬投票和软投票都会是一样的。
最后一个问题是,我可以使用像遗传算法这样的算法来为每个基础分类器寻找权重吗?我不知道如何实现它。
感谢您的所有教程。
抱歉我的英语不好。
你好,莉莉……你的大部分问题似乎都与优化有关。以下是一个很好的起点
https://machinelearning.org.cn/optimization-for-machine-learning-crash-course/
你好,
抱歉,我有个问题。我可以使用这种方法进行加权分位数和回归吗?
你好,Pari……以下资源是您感兴趣主题的绝佳起点
https://arxiv.org/pdf/2203.03032
抱歉,加权多数投票和加权平均多数投票有什么区别?
你好 Radit……以下资源可能有助于澄清
https://www.toptal.com/machine-learning/ensemble-methods-machine-learning
抱歉,我还有个问题。如何确定加权多数投票中的权重?有没有 Python 编码示例?