什么是集成学习?
本章会介绍机器学习领域中非常重要的集成学习方法。在机器学习中,集成学习方法使用多种学习算法来获得比使用任何单独的学习算法更好的预测性能。
集成学习类似新世纪福音战士(EVA)中名为 "三贤者" 的超级电脑。三贤者的创作者是赤木博士,三贤者可以看成拥有独立思维的三个不同身份,分别是赤木博士作为科学家的身份、作为母亲的身份以及作为女性的身份。对于同意或反对的决策问题,三贤者会根据三个不同的身份(三种不同的思维)分别给出对应的决策,最终根据 "少数服从多数" 的原则作出最终是同意还是反对的决策。三贤者就应用了集成学习的思路。
前面已经学习了很多机器学习算法,不同的机器学习算法考虑问题的方式有所不同,因此对于同一个问题不同的机器学习算法可能给出不同的结果。在这种情况下,我们完全可以应用集成学习的思路,让多个机器学习算法在同一个问题上分别进行学习并预测,最终根据 "少数服从多数" 的原则作出最终预测。
现实生活中,我们很多时候也在使用这种集成学习的思路。比如:
- 买东西找别人推荐。如果要买某种东西,我们通常会找多个朋友进行推荐,然后综合这些推荐意见来决定要买哪一个;
- 去电影院看电影。电影院新上映一部新电影,不确定这部电影到底好不好看(毕竟现在的电影票太贵了),你可能会上网查看不同人对这部电影的评价,看看评价好的人多还是评价坏的人多,然后决定看还是不看;
- 病情确诊。去医院检查,医院会给出检测报告,对于一些比较严重的疾病,可能会倾向于多跑几个医院或者多找几个大夫,多听听针对同一份报告,不同医院或者专家的意见;
实现集成学习
我们熟知很多机器学习算法,比如 kNN、逻辑回归、SVM、决策树,神经网络和贝叶斯等,这些算法都能够解决回归问题和分类问题(除了逻辑回归算法只能解决分类问题),因此面对同一个问题,可以让不同的机器学习算法去解决,最终根据 "少数服从多数" 的原则给出针对问题的最终结果。
通过上面的介绍,大致了解了集成学习,其实自己手动编写集成学习的代码并不难。具体来说,针对某一个二分类问题,将二分类训练集分别在逻辑回归、SVM 和决策树三种机器学习算法上进行训练,最终综合三种训练好的机器学习算法在测试集上的预测结果,根据 "少数服从多数" 的原则给出最终的预测结果。
接下来就通过手动的编写代码的方式来实现集成学习。
代码语言:javascript复制In[1]: import numpy as np
import matplotlib.pyplot as plt
本小节使用分布呈现交错半圆形的二分类虚拟数据集,使用 sklearn.datasets 包下的 make_moons 函数即可生成这样的虚拟数据集。
代码语言:javascript复制In[2]: from sklearn import datasets
X, y = datasets.make_moons(n_samples = 500,
noise = 0.3,
random_state = 42)
在使用 make_moons 函数时指定三个参数:
- n_samples,生成样本点的总数。默认为 100 个,由于本章需要的数据量相对比较大,因此将 n_samples 设置为 500;
- noise,加到数据集中的高斯噪声的标准差。默认为 None,noise 的值越小,生成的数据集呈现交错半圆形的分布形状越明显,noise 的值越大,生成的数据集呈现交错半圆形的分布形状越不明显,此时将 noise 设置为相对比较大的 0.3;
- random_state,随机种子。设置固定的随机种子,能够保证多次试验结果的一致性;
使用散点图将生成的虚拟数据集绘制出来。
代码语言:javascript复制In[3]: plt.scatter(X[y == 0, 0], X[y == 0, 1])
plt.scatter(X[y == 1, 0], X[y == 1, 1])
plt.show()
使用 train_test_split 方法将数据集划分为训练集和测试集。
代码语言:javascript复制In[4]: from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42)
- 首先使用逻辑回归算法。从 sklearn.linear_model 中导入 LogisticRegression 类,为了简单使用默认参数实例化逻辑回归分类器对象,调用 fit 方法对训练集进行拟合训练,最后调用 score 方法计算训练好的逻辑回归分类器在测试集上的准确度。
In[5]: from sklearn.linear_model import LogisticRegression
log_clf = LogisticRegression()
log_clf.fit(X_train, y_train)
log_clf.score(X_test, y_test)
Out[5]: 0.86
- 接下来使用 SVM 算法。从 sklearn.svm 中导入 SVC 类,为了简单使用默认参数实例化 SVM 分类器对象(SVM 分类器在 sklearn 中是 SVC 类),调用 fit 方法对训练集进行拟合训练,最后调用 score 方法计算训练好的 SVM 分类器在测试集上的准确度。
In[6]: from sklearn.svm import SVC
svm_clf = SVC()
svm_clf.fit(X_train, y_train)
svm_clf.score(X_test, y_test)
Out[6]: 0.88
- 最后使用决策树算法。从 sklearn.tree 中导入 DecisionTreeClassifier 类,为了简单使用默认参数实例化决策树分类器对象,调用 fit 方法对训练集进行拟合训练,最后调用 score 方法计算训练好的决策树分类器在测试集上的准确度。
In[7]: from sklearn.tree import DecisionTreeClassifier
dt_clf = DecisionTreeClassifier()
dt_clf.fit(X_train, y_train)
dt_clf.score(X_test, y_test)
Out[7]: 0.86399
接下来使用三种在同一个训练集上训练好的分类器对相同的数据集进行预测(这里使用X_test)。y_predict1、y_predict2 和 y_predict3 分别是三种训练好的分类器对 X_test 的预测结果。
代码语言:javascript复制In[8]: y_predict1 = log_clf.predict(X_test)
y_predict2 = svm_clf.predict(X_test)
y_predict3 = dt_clf.predict(X_test)
接下来使用集成学习方法,将三种训练好的分类器对 X_test 的预测结果根据 "少数服从多数" 的原则得到最终的预测结果 y_predict。实现也非常简单,只需要将 y_predict1、y_predict2 和 y_predict3 加在一起,判断累加的结果是否大于等于 2,如果对应预测结果大于等于 2 则表示至少有两个模型,至多有三个模型认为这个预测结果等于 1(二分类预测结果要不是 1 要不是 0),将最终布尔值转换为 int 类型(转不转都可以,Python 会将 True 看作 1,False 看作0)。
代码语言:javascript复制In[9]: y_predict = np.array((y_predict1 y_predict2 y_predict3) >= 2, dtype = 'int')
y_predict 是使用集成学习的方法得到对 X_test 的最终预测结果。
代码语言:javascript复制 In[10]: y_predict[:10]
Out[10]: array([1, 0, 0, 1, 1, 1, 0, 0, 0, 0])
使用 sklearn.metrics 包下的 accuracy_score 函数计算使用集成学习得到最终预测结果的准确率。
代码语言:javascript复制 In[11]: from sklearn.metrics import accuracy_score
accuracy_score(y_test, y_predict)
Out[11]: 0.896
通过集成学习得到的准确度为 0.896,显然要高于单独使用三种机器学习算法得到的准确度要高。换句话说,通过这种集成学习的方法提高了预测的准确度。
sklearn实现集成学习
sklearn 已经封装好了类来实现集成学习,只需要从 sklearn.ensemble 包下导入 VotingClassifier 类(ensemble 是集成的意思,集成学习为 ensemble learning)。sklearn 框架的设计和使用规范统一,因此使用 VotingClassifier 和使用其它机器学习算法的方法大致相同,首先实例化 VotingClassifier 类。
代码语言:javascript复制In[12]: from sklearn.ensemble import VotingClassifier
voting_clf = VotingClassifier(estimators = [
('log_clf', LogisticRegression()),
('svm_clf', SVC()),
('dt_clf', DecisionTreeClassifier())
], voting = 'hard')
实例化 VotingClassifier 类的同时指定两个参数:
- estimators,进行集成学习的多个估计器,简单来说就是进行集成学习的各个机器学习算法。传入的参数为元素为元组的 list 列表(和 pipeline 管道类似),其中每一个元组代表一个估计器,每一个元组又包含两个元素,第一元素为估计器的名称(可任意命名),第二个元素是估计器的实例对象;
- voting,表示最终决策方式,有 hard 和 soft 两个参数值;
接下来调用 fit 方法进行拟合训练。
代码语言:javascript复制 In[13]: voting_clf.fit(X_train, y_train)
Out[13]: VotingClassifier(estimators=[('log_clf', LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
verbose=0, warm_start=False)), ('svm_clf... min_weight_fraction_leaf=0.0, presort=False, random_state=None,
splitter='best'))],
flatten_transform=None, n_jobs=1, voting='hard', weights=None)
最后调用 score 方法计算在测试集上的准确度。
代码语言:javascript复制 In[14]: voting_clf.score(X_test, y_test)
Out[14]: 0.896
通过 sklearn 封装的 VotingClassifier 类实现的集成学习和前面手动实现的集成学习最终得到准确率的结果都是 0.896。这里需要注意,本小节实例化的三个机器学习算法使用的都是默认的参数,在具体的使用中,可以先找出每个机器学习算法在训练集上的最优参数,在使用 sklearn 实例化 VotingClassifier 类实现集成学习时,指定 estimators 参数,传入的机器学习算法实例对象时传入对应的最优参数。
References:
- Python3入门机器学习 经典算法与应用: https://coding.imooc.com/class/chapter/169.html#Anchor