机器学习之多模型融合预测iris数据集

一、多模型融合

众所周知,机器学习可以通过多个模型融合来提升模型的性能,近些年的各种算法大赛中前几名几乎都是多模型融合,比如在kaggle上的otto产品分类挑战赛中取得冠军和亚军成绩的模型都是融合了1000+模型的“庞然大物”。某种层面上讲,多模型融合是一种对数据的“暴力”解法,通过若干模型来提升性能,当然也有大神通过数据前期处理+单模型也能达到多模型同样的效果,不过楼主还是比较懒,懒得分析数据之间的关系,以及特征分析等工作。废话不多说,进入我们的正题吧!

二、多模型融合的方式

1、Voting/Average

真实标签 1 0 1 0 1 1 0 1 1 1
分类器1 1 0 1 0 1 0 0 0 1 1
分类器2 1 1 1 0 1 1 1 1 1 1
分类器3 1 1 0 0 1 1 1 1 1 0

从上表我们可以看出:
分类器1的accuracy=0.8
分类器2的accuracy=0.8
分类器3的accuracy=0.6
如果按照少数服从多数的原则,则模型融合后的accuracy=0.8

1.1 发现问题

你可能发现使用多模型融合后,模型的性能并没有提升,这一方面可能是投票的模型太少,某些模型恰好都把某个样本分错了,导致模型融合后性能提升不明显,另一方面,也可能与模型之间的差异过小有关,我们再来看一个例子。

真实标签 1 0 1 0 1 1 0 1 1 1
分类器1 1 0 1 0 1 0 0 0 1 1
分类器2 0 1 1 0 1 1 0 1 0 1
分类器3 1 0 0 0 1 1 1 0 1 0

从上表我们可以看出:
分类器1的accuracy=0.8
分类器2的accuracy=0.7
分类器3的accuracy=0.6
如果按照少数服从多数的原则,则模型融合后的accuracy=0.9

1.2 为什么

通过观察我们发现后面的实验中,模型的差异更大,换句话说,就是模型在不同的样本上出错,第一个实验accuracy低或者无提升的原因是模型之间的相关性较高,都在同一个或者几个样本上出错,这样就会导致融合模型性能无提升甚至下降。

1.3 结论

对于模型融合,模型之间差异越大,融合所得的结果将会更好。这里所指模型之间的差异,并不是指正确率的差异,而是指模型之间相关性的差异。

三、利用机器学习自带的iris数据集进行多模型融合

通过上面的实验,我们利用sklearn中的Voting包来实现一个多模型融合的例子

1、导入所需的包

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier, VotingClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split, StratifiedKFold
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score

2、数据读取

iris = load_iris()
data = iris.data
labels = iris.target

3、划分训练集、测试集、及10折交叉验证

x_train, x_test, y_train, y_test = train_test_split(data, labels, test_size=0.3, random_state=10)
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=10)

4、模型构建

# 模型
cls_knn = KNeighborsClassifier(n_neighbors=3)
cls_gnb = GaussianNB()
cls_dt = DecisionTreeClassifier(random_state=10)

这里只用到了3种分类器,分别是K近邻、高斯贝叶斯和决策树,没有选择很多分类器的原因是,其他的分类器和这3种算法原理差不多,不能达到我们一开始说的模型差异要大。

投票及性能比较

# 投票
voting = VotingClassifier(estimators=[('knn', cls_knn), ('gnb', cls_gnb),
                                      ('dt', cls_dt)], voting='hard', weights=[2, 1, 1])

# 比较性能(10折交叉验证)
acc_list = []
for clf in (cls_knn, cls_gnb, cls_dt, voting):
    for k, (train, test) in enumerate(kfold.split(x_train, y_train)):
        clf.fit(x_train[train], y_train[train])
        y_pred = clf.predict(x_test)
        acc = accuracy_score(y_test, y_pred)
        acc_list.append(acc)
    print(clf.__class__.__name__, np.mean(acc_list))
    acc_list.clear()

四、结果

KNeighborsClassifier 0.9577777777777777
GaussianNB 0.9533333333333334
DecisionTreeClassifier 0.9333333333333333
VotingClassifier 0.9488888888888889

第一次给出的结果如上所示,我们发现投票后的acc竟然不如K近邻以及高斯贝叶斯,这可能还是出现了分类器之间差异过小的问题,他们不约而同的在部分数据上集体出错,所以,换一种思路,现在我让投票的权重发生改变,优先训练KNN,使其acc最大化,然后赋予其较大的权重,这有点像班里的好学生做的题正确率高,另外2名同学正确率低一些,那我们就让成绩最好的同学的比例大一些,同时调整模型超参数,进一步提升模型性能。

KNeighborsClassifier 0.9844444444444445
GaussianNB 0.9888888888888889
DecisionTreeClassifier 0.96
VotingClassifier 0.9911111111111112

按照2:1:1的权重我们发现模型融合准确率确有提升,目的达成!

猜你喜欢

转载自blog.csdn.net/JaysonWong/article/details/125097257