集成学习打卡-07
投票法
投票法的原理
在之前章节中对模型的偏差-方差分解”说明:泛化性能是由学习算法的能力、数据的充分性以及学习任务本身的难度所共同决定的。在我们给定学习任务后,为了取得好的泛化性能,可以减小偏差拟合数据,同时可以降低方差,使得数据产生的扰动对模型影响小。投票法是一种遵循少数服从多数原则的集成学习模型,通过多个模型的集成降低方差,从而提高模型的鲁棒性。
具体地投票法在回归模型与分类模型上均可使用:
(1) 回归投票法:预测结果是所有模型预测结果的平均值。
(2) 分类投票法:预测结果是所有模型种出现最多的预测结果。 分类投票法又可以被划分为硬投票与软投票:
分类投票法又可以被划分为硬投票与软投票:
(1)硬投票:预测结果是所有投票结果最多出现的类。
(2)软投票:预测结果是所有投票结果中概率加和最大的类。
举一个栗子说明硬投票:
对于图像识别猫狗问题来说:
模型 1 的预测结果是猫
模型 2 的预测结果是猫
模型 3 的预测结果是狗
有2/3的模型预测结果是猫,因此硬投票法的预测结果是猫
同样的例子说明软投票:
模型 1 的预测结果是狗的概率为 49%
模型 2 的预测结果是狗的概率为 49%
模型 3 的预测结果是狗的概率为 99%
最终对于类别A的预测概率的平均是 ( 49 + 49+99) / 3 = 65.67%,而猫的概率为34.33%因此软投票法的预测结果是狗。从这个例子我们可以看出,软投票法与硬投票法可以得出完全不同的结论。相对于硬投票,软投票法考虑到了预测概率这一额外的信息,因此可以得出比硬投票法更加准确的预测结果。
需要注意的是:在投票法中,我们还需要考虑到不同的基模型可能产生的影响。
(1)基模型之间的效果不能差别过大。当某个基模型相对于其他基模型效果过差时,该模型很可能成为噪声。
(2)基模型之间应该有较小的同质性。例如在基模型预测效果近似的情况下,基于树模型与线性模型的投票,往往优于两个树模型或两个线性模型。
投票法的案例分析
# -*- coding: utf-8 -*-
from sklearn.ensemble import VotingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score, RepeatedKFold
from sklearn.datasets import make_classification
from matplotlib import pyplot
import numpy as np
##创建数据集
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
#投票集成
def get_voting():
models = []
for i in range(1, 10, 2):
models.append(('knn' + str(i), KNeighborsClassifier(n_neighbors=i)))
ensemble = VotingClassifier(estimators= models, voting='hard')
return ensemble
#保存模型为了后续比较
def get_models():
models = dict()
for i in range(1, 10, 2):
models['knn'+str(i)]= KNeighborsClassifier(n_neighbors=i)
models['hard_voting']=get_voting()
return models
#评价模型
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='accuracy', cv=cv, error_score='raise')
return scores
def main():
X,y = get_dataset()
models = get_models()
results, names = list(), list()
for name, model in models.items():
score = evaluate_model(model,X,y)
results.append(score)
names.append(name)
print('>%s %.3f (%.3f)' % (name, np.mean(score), np.std(score)))
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
if __name__ == '__main__':
main()
参考链接: https://blog.csdn.net/wwh578867817/article/details/50464922.
参考链接: https://www.zhihu.com/question/22928442/answer/354885414.
参考链接: https://github.com/datawhalechina/team-learning-data-mining/tree/master/EnsembleLearning.