集成学习:
不同的算法对同一问题进行分析。 然后进行投票处理。少数服从多数
模拟集成学习
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
X_train, X_test, y_train,y_test = train_test_split(X,y, random_state=42)
# 逻辑回归
from sklearn.linear_model import LogisticRegression
log_clf = LogisticRegression()
log_clf.fit(X_train, y_train)
log_clf.score(X_test,y_test) # 0.864
# svm
from sklearn.svm import SVC
svm_clf = SVC()
svm_clf.fit(X_train,y_train)
svm_clf.score(X_test, y_test) # 0.888
# 决策树
from sklearn.tree import DecisionTreeClassifier
dt_clf = DecisionTreeClassifier()
dt_clf.fit(X_train,y_train)
dt_clf.score(X_test,y_test) # 0.84
# 对每种模型进行预测
y_predict1 = log_clf.predict(X_test)
y_predict2 = svm_clf.predict(X_test)
y_predict3 = dt_clf.predict(X_test)
# 挑出 大于等于2的,也就是2/3以上都是1的,类似于投票过程
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 ) # 0.896
scikit-learn中集成学习
和原来的Pipeline 参数有点类似
from sklearn.ensemble import VotingClassifier
voting_clf = VotingClassifier(estimators=[
('log_clf',LogisticRegression()),
('svm',SVC()),
('dt_clf',DecisionTreeClassifier())
],voting='hard'
)
voting_clf.fit(X_train,y_train)
voting_clf.score(X_test, y_test) # 0.896
# 和上面的模拟结果一致
上面参数中 voting=‘hard’ ,这个也可以使‘soft’
- hard : 少数服从多数,
- soft: 有权值的投票
soft 方式
soft方式要求集合的每个模型都能估计概率
逻辑回归本身就是基于概率模型,其中 predict_proba 函数可以估计概率
knn 算法:可以计算概率
决策树: 占比最大的数据/节点上的所有数据
svm: svm是寻找margin 的算法,但是可以通过一些方式也可以计算概率。svc中的 参数 probability ,如果设置其为True,可以计算出某个样本的概率
from sklearn.ensemble import VotingClassifier
voting_clf = VotingClassifier(estimators=[
('log_clf',LogisticRegression()),
('svm',SVC(probability=True)), # 设置SVC 的probability参数为True
('dt_clf',DecisionTreeClassifier(random_state=666))
],voting='soft'
)
voting_clf.fit(X_train,y_train)
voting_clf.score(X_test, y_test) # 0.912
虽然有很多机器学习算法,但从投票的角度来看,仍然不够多。
所以需要创建更多的子模型,集成更多的子模型的意见。
子模型之间不能一致,子模型之间要有差异性。
如何创建差异性?
- 每个子模型只看样本数据的一部分
例如:一共500个样本数据,每个子模型只看100个样本数据。- 每个子模型不需要太高的准确率
如果每个子模型只有51%的准确率,
如果我们只有1个子模型,整体准确率:51%
如果我们只有3个子模型,整体准确率: 0.5 1 3 + C 3 2 ⋅ 0.5 1 2 ⋅ 0.49 0.51^3+C_3^2 \cdot 0.51^2 \cdot 0.49 0.513+C32⋅0.512⋅0.49 = 51.5%
如果我们有500个子模型。整体准确率: ∑ i = 251 500 C 500 i ⋅ 0.5 1 i ⋅ 0.4 9 500 − i \sum_{i=251}^{500} C_{500}^i \cdot 0.51^i \cdot 0.49^{500-i} ∑i=251500C500i⋅0.51i⋅0.49500−i = 65.6% - 假如每个子模型的准确率只有60%的准确率,
那么500个子模型的准确率是: ∑ i = 251 500 C 500 i ⋅ 0. 6 i ⋅ 0. 4 500 − i \sum_{i=251}^{500} C_{500}^i \cdot 0.6^i \cdot 0.4^{500-i} ∑i=251500C500i⋅0.6i⋅0.4500−i = 99.999%
- 每个子模型不需要太高的准确率
- 取样: 放回取样,不放回取样
- 放回取样 :Bagging
更加常用,
样本少时也可以训练很多个子模型
不是很依赖随机。
统计学中叫 bootstrap
- 不放回取样:Pasting
- 放回取样 :Bagging
Bagging
- scikit-learn中放回取样
# 使用svm 测试
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier
bagging_clf = BaggingClassifier(DecisionTreeClassifier(), n_estimators=500, max_samples=100, bootstrap=True)
# 如果将bootstrap参数改为 False,就会变成不放回取样
# n_estimators 子模型数量
# max_samples 每个子模型的需要的数据量
bagging_clf.fit(X_train,y_train)
bagging_clf.score(X_test,y_test) # 0.92
- OOB out of Bag
放回取样导致会有一部分样本很有可能没有取到
平均大约有37%的样本没有取到,这样的样本就叫 oob
不使用测试数据集,而使用这部分没有取到的样本做测试,验证
oob_score_ 就可以自动使用oob数据作为测试数据集来得到验证结果
bagging_clf = BaggingClassifier(DecisionTreeClassifier(), n_estimators=500, max_samples=100, bootstrap=True,oob_score=True)
# 需要传入参数 oob_score设置为 True 才能在后面调用 oob_score_
bagging_clf.fit(X,y)
bagging_clf.oob_score_ # 0.92
- Bagging 的思路极易并行化处理
n_jobs = -1,
%%time
bagging_clf = BaggingClassifier(DecisionTreeClassifier(), n_estimators=5000, n_jobs=-1, max_samples=100, bootstrap=True,oob_score=True)
bagging_clf.fit(X,y)
bagging_clf.oob_score_
- 其他产生子模型差异化的方式:
-
针对特征进行随机采样 bootstrap_features
一般用于在样本数据特征特别多的情况下,如图像识别
Random Subspaces
参数 : max_features=1,bootstrap_features=True -
既针对样本,又针对特征进行随机采样
Random Patches
-
# 针对特征进行随机采样
random_subspaces_clf = BaggingClassifier(DecisionTreeClassifier(), n_estimators=500, max_samples=500,
bootstrap=True,oob_score=True,
max_features=1,bootstrap_features=True
)
random_subspaces_clf.fit(X,y)
random_subspaces_clf.oob_score_ # 0.85
# 既针对样本,又针对特征进行随机采样
random_patches_clf = BaggingClassifier(DecisionTreeClassifier(), n_estimators=500, max_samples=100,
bootstrap=True,oob_score=True,
max_features=1,bootstrap_features=True
)
random_patches_clf.fit(X,y)
random_patches_clf.oob_score_ # 0.856
上面使用 bagging的方式集成了大量的决策树,这种方式也叫 随机森林
随机森林
使用决策树进行集成学习叫做 随机森林
sklearn中为我们还专门提供了随机森林的类,还提供了更多的随机性
决策树在节点划分上,在随机的特征子集上寻找最优划分特征
- sklearn中的随机森林
from sklearn.ensemble import RandomForestClassifier
rf_clf = RandomForestClassifier(n_estimators=500, random_state=666,
oob_score=True, n_jobs=-1
)
rf_clf.fit(X,y)
rf_clf.oob_score_ # 0.892
可以看出随机森林中包含决策树和 bagging的部分参数
Extra-Trees
及其随机的森林
在决策树的节点划分上,使用随机的特征和随机的阈值
提供额外的随机性,抑制了过拟合(方差),但增大了bias(偏差)
跟快的训练速度
sklearn中extra-trees
from sklearn.ensemble import ExtraTreesClassifier
et_clf = ExtraTreesClassifier(n_estimators=500, bootstrap=True,oob_score=True, random_state=666)
et_clf.fit(X,y)
et_clf.oob_score_ # 0.892
集成学习解决回归问题
from sklearn.ensemble import BaggingRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import ExtraTreesRegressor
Boosting
集成多个模型
每个模型都在尝试增强(Boosting)整体的效果
-
Ada Boosting
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
ada_clf = AdaBoostClassifier(DecisionTreeClassifier(max_depth=2), n_estimators=500)
ada_clf.fit(X_train,y_train)
ada_clf.score(X_test,y_test)
Gradient Boosting
训练一个模型m1,产生错误e1
针对e1训练第二个模型m2, 产生错误 e2
针对e2训练第二个模型m3, 产生错误 e3
…
最终预测结果是: m1 + m2 +m3 + …
from sklearn.ensemble import GradientBoostingClassifier
# 因为 GradientBoostingClassifier 本身就是基于 决策树的,所以不用传入基本模型
gb_clf = GradientBoostingClassifier(max_depth=2, n_estimators=30)
gb_clf.fit(X_train,y_train)
gb_clf.score(X_test,y_test) # 0.912
使用 Boosting 解决回归问题
from sklearn.ensemble import AdaBoostRegressor
from sklearn.ensemble import GradientBoostingRegressor
...
Stacking
这样可以多层叠加
上图可以看出要将数据集分成3份,每层一份
可以看出使用几层,每层几个,都是超参数
这是一种复杂的方式。越复杂越容易过拟合
sklearn中没有提供stacking模型的方法