一,什么是集成学习
什么是集成学习
把不同的算法都运用起来对同一个东西进行决策,再用这个算法对其他算法进行投票,少数服从多数,票数多的胜。
比如生活中购买东西,我们一般不会只找一个人推荐,而是找多个人的评价再做出决定,这就是集成学习。
即集成不同人的意见进行决策。
其实,样本整体相当于一个病人,样本里的数据就是病人的特征,算法可以看作是治病方案并决定怎么才算是生病,判断是否病人有病,当患者有重大疾病,通常需要听取很多医生的建议才可以下定论。
因此设计程序只需要使用不同的算法对同一数据进行分析。
sklearn包中包含算法:Voting Classifier
数据生成:
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
X, y = datasets.make_moons(n_samples=500, noise=0.3, random_state=42)
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()
手动分类决策:
使用逻辑回归
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
log_clf = LogisticRegression()
log_clf.fit(X_train, y_train)
log_clf.score(X_test, y_test)
使用SVM
from sklearn.svm import SVC
svm_clf = SVC()
svm_clf.fit(X_train, y_train)
svm_clf.score(X_test, y_test)
使用决策树
from sklearn.tree import DecisionTreeClassifier
dt_clf = DecisionTreeClassifier(random_state=666)
dt_clf.fit(X_train, y_train)
dt_clf.score(X_test, y_test)
投票
y_predict1 = log_clf.predict(X_test)
y_predict2 = svm_clf.predict(X_test)
y_predict3 = dt_clf.predict(X_test)
y_predict = np.array((y_predict1 + y_predict2 + y_predict3) >= 2, dtype='int')
检查投票结果:
from sklearn.metrics import accuracy_score
accuracy_score(y_test, y_predict)
提高了数据准确度
sklearn随机森林决策:
from sklearn.ensemble import VotingClassifier
#类似pipline
voting_clf = VotingClassifier(estimators=[ #估计器
('log_clf', LogisticRegression()),
('svm_clf', SVC()),
('dt_clf', DecisionTreeClassifier(random_state=666))],
voting='hard')
voting_clf.fit(X_train, y_train)
voting_clf.score(X_test, y_test)
二,Soft Voting Classifier
投票要考虑到投票的权重问题,比如唱歌比赛中,观众投票占的比重肯定是低于专业评委的比重的,也就是专业评委投的票更具有权威性,因此他们的权重会高一些,这就是软投票。硬投票就是把所有的投票人不论专业不专业,无论他们决策水平怎么样都一视同仁。
在soft中,还要考虑算法有多大的概率确认是某类,这个模型越确定投给某一类,我们就更相信它。
这样,我们就要求集合的每一个模型都可以估计概率->逻辑回归,使用predict_prob函数进行概率预测。可以回顾哪些算法支持概率预测:
- 逻辑回归本身就是基于概率模型的
- KNN也可以支持概率预测,并且可以根据距离加入权重
- 决策树算法类似KNN,可以用占比例最大的数据点数量/叶子中所有数据点的数量表示概率
- SVM也可以计算概率,SVC中有自带的probility进行预测,但会牺牲一定的计算时间
程序实现:
数据同上
voting_clf2 = VotingClassifier(estimators=[
('log_clf', LogisticRegression()),
('svm_clf', SVC(probability=True)),
('dt_clf', DecisionTreeClassifier(random_state=666))],
voting='soft')
voting_clf2.fit(X_train, y_train)
voting_clf2.score(X_test, y_test)
三,Bagging和Pasting
虽然有很多机器学习方法,但是从投票的角度看,仍然不够
要创建更多的子模型,集成更多的子模型的意见,并且子模型之间不能一致,要有差异性!
如何创建差异性?
每个模型只看样本数据的一部分。
比如,有500个样本数据,5个子模型,每个子模型只看100个样本数据。
如果我们只有一个子模型,整体准确率是51%
如果有3个子模型,整体准确率是0.51^3+C(3,2)*0.51^2*0.49=51.5%
如果有500个子模型,整体准确率是65.6%
随着子模型的增加,整体的准确率会提高
而如果每个子模型的准确率是60%
500个子模型的准确率是99.999%(理论上)
因此使用集成学习的频率很高
取样:放回取样(Bagging)(更常用),不放回取样(Pasting)
统计学中的放回取样叫做:bootstrap
程序实现:
数据同上,产生训练与测试数据集
使用Bagging:
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier
#在这里集成的模型都是决策树模型,因为决策树非参数模型更容易产生差异比较大的子模型
bagging_clf = BaggingClassifier(DecisionTreeClassifier(),
n_estimators=500, max_samples=100,
bootstrap=True)
#n_estimators表示集成多少决策树模型,max_samples表示每个子模型要看多少样本,bootstrap表示放回或者不放回取样,有很多决策树,因此叫做随机森林
bagging_clf.fit(X_train, y_train)
bagging_clf.score(X_test, y_test)
四,oob(Out-of-Bag)和更多关于Bagging的讨论
对于放回取样会导致有一些样本很可能没有取到,平均有37%的样本取不到,就是oob
不使用测试数据集,而是使用这部分没有被取样的样本oob作为测试/验证数据集
使用sklearn中的oob_score_属性
数据样本依旧如上,但是没有train_test_split这一步
使用oob
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier
bagging_clf = BaggingClassifier(DecisionTreeClassifier(),
n_estimators=500, max_samples=100,
bootstrap=True, oob_score=True)
bagging_clf.fit(X, y)
bagging_clf.oob_score_
Bagging的思路非常容易进行并行化处理
因此可以用到n_jobs进行并行操作
bagging_clf = BaggingClassifier(DecisionTreeClassifier(),
n_estimators=500, max_samples=100,
bootstrap=True, oob_score=True,
n_jobs=-1) #使用所有的核
bagging_clf.fit(X, y)
Bagging的更多讨论
产生差异化的方式还有:
- 针对特征进行随机采样(Random Subspaces) 样本特别多的情况下,比如图像
- 即针对样本又针对特征进行随机采样(Random Patches),表示即在行的方向上随机又在列的方向上随机,因为取样的图像像补丁,因此得名。
在特征空间上进行的采样也叫做(bootsrap_features)
random_subspaces_clf = BaggingClassifier(DecisionTreeClassifier(),
n_estimators=500, max_samples=500, #相当于没有对样本数据随机
bootstrap=True, oob_score=True,
max_features=1, bootstrap_features=True)
#max_features表示每次看几个特征,bootstrap_features=True表示放回采样
random_subspaces_clf.fit(X, y)
random_subspaces_clf.oob_score_
五,随机森林和Extra-Trees
随机的提取样本及其特征,集成了很多的决策树,因此被称为随机森林
使用以上数据集:
from sklearn.ensemble import RandomForestClassifier
rf_clf = RandomForestClassifier(n_estimators=500, oob_score=True, random_state=666,
n_jobs=-1)
rf_clf.fit(X, y)
rf_clf2 = RandomForestClassifier(n_estimators=500, max_leaf_nodes=16,
oob_score=True, random_state=666, n_jobs=-1)
rf_clf2.fit(X, y)
rf_clf2.oob_score_
Extra-Trees
极其随机的随机森林,决策树在节点划分上,使用随机的特征和随机的阈值,提供额外的随机性,抑制过拟合(随机取数据使得大多数子模型不会被几个数据带偏),但是增大了bias(增大偏差,抑制方差),并且这个方式还会增加训练速度(相较于随机森林)
from sklearn.ensemble import ExtraTreesClassifier
et_clf = ExtraTreesClassifier(n_estimators=500, bootstrap=True, oob_score=True,
random_state=666, n_jobs=-1)
et_clf.fit(X, y)
使用集成学习解决回归问题:
from sklearn.ensemble import BaggingRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import ExtraTreesRegressor
六,Ada-Boosting和Gradient-Boosting
Boosting:增强推动
也是集成多个子模型,但是这些子模型彼此间不是独立的关系,而是,每个子模型都在尝试增强(Boosting)整体的效果
AdaBoosting是什么?
假设解决的是回归问题,上图中浅色的蓝点表示模型成功预测的点,深蓝色的点表示没有被预测到。之后我们重新学习数据样本时,让浅蓝色样本点所占比列小一点(因为已经可以学到了),让深蓝色样本点的学习权重更大一些,这样慢慢的就会逐渐接近真实模型。
因此在ada-boosting中,他会认为有一些数据点是重要的,另外一些不重要,之后从一个子模型延申出很多的子模型,这些子模型看的是同样的数据样本点,只不过他们对数据点赋予的权重是不同的,这样就形成了差异性,最后再让这些子模型综合投票进行预测。
程序实现:
使用以上数据集
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier #调用分类器
#随机森林是集成学习的一种方法,所以是ensemble
ada_clf = AdaBoostClassifier(
DecisionTreeClassifier(max_depth=2), n_estimators=500)
ada_clf.fit(X_train, y_train)
通过调正参数还可以进一步提高
Gradient Boosting是什么?
所有的算法都会出错误
某算法针对所有的数据集进行训练,得到一个模型m1,产生的错误是e1;
现在针对e1训练出第二个模型m2,产生的错误是e2;
再针对e2训练第三个模型m3,产生的错误是e3;
……
最终的预测结果是:m1+m2+m3+…
左侧列从上到下依次是图1-3,右侧列从上到下依次是图4-6
图一是第一次预测的模型,得到的绿色线就是m1,图二是图一模型犯的错误e1,
程序实现:
from sklearn.ensemble import GradientBoostingClassifier
gb_clf = GradientBoostingClassifier(max_depth=2, n_estimators=30)
gb_clf.fit(X_train, y_train)
Boosting解决回归问题:
from sklearn.ensemble import AdaBoostRegressor
from sklearn.ensemble import GradientBoostingRegressor
七,Stacking集成学习
对于voting classifier的思路是使用几个不同的算法,每个算法都进行预测,之后综合这几个算法的结果就可以。分类问题可以少数服从多数,回归问题可以取平均值。
Stacking的思路是:同样使用几个模型进行预测,但是我们不用预测结果进行投票,而是使用预测结果训练一个新的模型,再利用新的模型的预测结果作为最终结果。如下图所示:
回归的模型也可以用来预测,只需要回归算出概率就可以。同样回归问题也可以转换为分类问题,就是求取平均值实现。
Stacking要做的就是把训练数据集分为俩分,其中一份用来训练三个模型(如下图),另外的数据训练上边的模型(stacking)
更复杂的Stacking模型:
太复杂容易过拟合。这个模型已经接近神经网络了!