集成学习和随机森林

集成学习和随机森林


zhenxiang.gif

机器学习技巧:真香


什么是集成学习(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])
<matplotlib.collections.PathCollection at 0x9c77048>
output_3_1.png
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.neighbors import KNeighborsClassifier  # KNN

knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train, y_train)
knn_clf.score(X_test, y_test)
0.912
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)
0.864
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

手动集成三种算法学习结果

y_predict1 = knn_clf.predict(X_test)
y_predict2 = dt_clf.predict(X_test)
y_predict3 = log_clf.predict(X_test)
y_predict3
array([1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1,
       1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0,
       0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0,
       0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0,
       1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1,
       1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0], dtype=int64)
# 三种算法预测结果,相同的预测结果大于等于2个,返回True,否则False,结果转为整型1/0
# 三种算法结果:0,0,0返回0;0,0,1返回0;0,1,1返回1;1,1,1返回1
# 相加,四种可能
# 0,1,2,3,前两种返回0,后两种返回1

y_predict1 + y_predict2 + y_predict3

y_predict = np.array((y_predict1 + y_predict2 + y_predict3) >= 2, dtype=np.int)
y_predict
array([1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1,
       1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0,
       0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0,
       0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0,
       1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1,
       1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0])
from sklearn.metrics import accuracy_score
accuracy_score(y_test, y_predict)
0.92

使用Voting Classifier自动集成学习

建议先分别执行各个算法,调好参数后再统一集成到一起

from sklearn.ensemble import VotingClassifier

voting_clf = VotingClassifier(
    estimators=[
        ('dt_clf', DecisionTreeClassifier(random_state=666)),
        ('knn_clf', KNeighborsClassifier()),
        ('log_clf', LogisticRegression())
    ],
    voting='hard'
)
voting_clf.fit(X_train, y_train)  # 训练
VotingClassifier(estimators=[('dt_clf', DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
            max_features=None, max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_...ty='l2', random_state=None, solver='liblinear', tol=0.0001,
          verbose=0, warm_start=False))],
         flatten_transform=None, n_jobs=1, voting='hard', weights=None)
voting_clf.predict(X_test)  # 预测
e:\Anaconda3\lib\site-packages\sklearn\preprocessing\label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.
  if diff:





array([1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1,
       1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0,
       0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0,
       0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0,
       1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1,
       1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0], dtype=int64)
voting_clf.score(X_test, y_test)  # 准确率
e:\Anaconda3\lib\site-packages\sklearn\preprocessing\label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.
  if diff:





0.92

参数voting值

  • hard
  • soft

例:某数据有2种分类,使用五种模型训练并预测,得到结果为:

模型1:A 99%;B 1%
模型2:A 49%;B 51%
模型3:A 40%;B 60%
模型4:A 90%;B 10%
模型5:A 30%;B 70%
  • hard voting模式:考虑投票数。
    • A:2票
    • B:3票
    • 最终结果为B
  • soft voting模式:考虑投票权重
    • A = (0.99+0.49+0.4+0.9+0.3)/5 = 0.616
    • B = (0.01+0.51+0.6+0.1+0.7)/5 = 0.384
    • 最终结果为A

soft voting要求集成的每个模型都能估计概率,否则无法运算(kNN、决策树、逻辑回归都可以)

voting_clf = VotingClassifier(
    estimators=[
        ('dt_clf', DecisionTreeClassifier(random_state=666)),
        ('knn_clf', KNeighborsClassifier()),
        ('log_clf', LogisticRegression())
    ],
    voting='soft'
)
voting_clf.fit(X_train, y_train)
voting_clf.score(X_test, y_test)
e:\Anaconda3\lib\site-packages\sklearn\preprocessing\label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.
  if diff:





0.888

更好的集成学习方式

现有的集成学习方式,能用于集成的模型太少,想要提高集成学习的准确率需要:

  • 创建和集成更多子模型
  • 子模型之间不能一致,要有差异性

子模型不需要太高的准确率,只要足够多,就可以极大提升最终模型准确率

例如:每个子模型有60%准确率

  • 如果只有一个子模型,准确率60%
  • 如果有3个子模型:0.6^{3}+c^{2}_{3}\cdot 0.6^{2}\cdot 0.4 =0.648
  • 如果有500个子模型:\sum ^{500}_{i=251}C^{i}_{500}\cdot 0.6^{i}\cdot 0.4^{500-i} =0.9999

注意:子模型的准确率最好高于平均准确率

0.6 ** 3 + (2*3/2*1) * 0.6**2 * 0.4
0.648

如何产生大量有差异的子模型?

  • 机器学习算法就那么点,无法生成大量子模型
  • 随机抽样方式,每个子模型只抽取一部分样本进行训练
    • 例如:所有子模型都用一个算法,训练集500条数据,每个子模型随机抽取100条进行训练,可以生成任意多个子模型
    • 子模型算法基本只使用决策树算法,因为决策树大量的剪枝方式可以生成差异更大的模型,优于其他模型

两种采样方式:

Bagging:放回采样(bootstrap),更常用,能制造更多子模型
Pasting:不放回采样

使用Bagging方式集成学习

这里Bagging方式集成学习只使用决策树模型,

通过改变训练数据生成子模型,决策树大量的剪枝方式可以生成差异更大的模型,优于其他模型

from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier
bagging_clf = BaggingClassifier(
    DecisionTreeClassifier(),  # 集成的模型
    n_estimators=500,  # 集成多少个子模型
    max_samples=100,  # 每个子模型需要多少训练数据
    bootstrap=True)  # 放回采样

bagging_clf.fit(X_train, y_train)
bagging_clf.score(X_test, y_test)
0.92

子模型越多,准确率越高

bagging_clf = BaggingClassifier(
    DecisionTreeClassifier(),  # 集成的模型
    n_estimators=5000,  # 集成多少个子模型
    max_samples=100,  # 每个子模型需要多少训练数据
    bootstrap=True)  # 放回采样

bagging_clf.fit(X_train, y_train)
bagging_clf.score(X_test, y_test)
0.912

没有99%那么多,因为一些子模型准确率会低于均值


OOB:out of bag

放回采样导致一部分样本始终没有被用于训练

平均约有37%的样本没有被用到

所以不需要分离测试集,直接使用没有被用过的样本数据做测试集即可

bagging_clf = BaggingClassifier(
    DecisionTreeClassifier(),
    n_estimators=500,
    max_samples=100,
    bootstrap=True,
    oob_score=True)  # OOB为True

bagging_clf.fit(X, y)  # 训练数据采用全部样本数据,不需要测试集
bagging_clf.oob_score_  # 调用OOB方法计算准确率
0.916

n_jobs 并行化处理

Bagging非常易于并行化处理

每个子模型可以独立训练,使用独立cpu内核,加快速度

注意:如果训练时间非常久,同时使用所有内核 n_jobs=-1, 非常容易卡死,训练完成后才能恢复运算

%%time
bagging_clf = BaggingClassifier(
    DecisionTreeClassifier(),
    n_estimators=500,
    max_samples=100,
    bootstrap=True,
    oob_score=True)

bagging_clf.fit(X, y)
Wall time: 999 ms
%%time
bagging_clf = BaggingClassifier(
    DecisionTreeClassifier(),
    n_estimators=500,
    max_samples=100,
    bootstrap=True,
    oob_score=True,
    n_jobs=3)  # 使用3个cpu内核

bagging_clf.fit(X, y)
Wall time: 3.59 s

更多Bagging方式

除了针对样本数据进行随机采样,还有更多方式

  • 针对特征进行随机采样,Random Subspaces
  • 既针对样本、又针对特征进行随机采样,Random Patches

bootstrap_features 针对特征随机取样

random_subspaces_clf = BaggingClassifier(
    DecisionTreeClassifier(),
    n_estimators=500,
    max_samples=500,  # 关闭样本随机采样,因为子模型需要数据,设为全部500条,不再选取部分数据
    bootstrap=True,
    oob_score=True,
    max_features=1,  # 随机取1列特征(因为数据一共就2列特征)
    bootstrap_features=True)  # 对特征随机采样,放回采样

random_subspaces_clf.fit(X, y)
random_subspaces_clf.oob_score_
0.834

既对样本、又对特征进行随机采样

random_patches_clf = BaggingClassifier(
    DecisionTreeClassifier(),
    n_estimators=500,
    max_samples=100,  # 打开样本随机采样
    bootstrap=True,
    oob_score=True,
    max_features=1,  # 随机取1列特征(因为数据一共就2列特征)
    bootstrap_features=True)  # 对特征随机采样,放回采样

random_patches_clf.fit(X, y)
random_patches_clf.oob_score_
0.856

随机森林

上面使用决策树、以Bagging集成学习的方式,就是随机森林

除了手动集成学习外,sklearn自带一个随机森林类,可以方便的创建随机森林模型

随机森林模型集成了决策树和Bagging分类器,所以拥有决策树和BaggingClassifier的所有参数

from sklearn.ensemble import RandomForestClassifier
rf_clf = RandomForestClassifier(
    n_estimators=500,  # 500棵树
    oob_score=True,  # 使用未被抽取的数据做测试集
    random_state=666,  # 随机数种子固定
    n_jobs=-1)  # 所有cpu内核并行运算

rf_clf.fit(X, y)
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
            max_depth=None, max_features='auto', max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, n_estimators=500, n_jobs=-1,
            oob_score=True, random_state=666, verbose=0, warm_start=False)
rf_clf.oob_score_
0.896

调节参数,提升准确率

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_
0.92

集成学习解决回归问题的子库

from sklearn.ensemble import BaggingRegressor
from sklearn.ensemble import RandomForestRegressor

Boosting

  • Bagging:集成多个模型
  • Boosting:每个模型都在尝试增强(Boosting)整体效果

Ada Boosting

adaboosting.png

Ada Boosting

from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
ada_clf = AdaBoostClassifier(
    DecisionTreeClassifier(max_depth=2),  # 基础学习算法
    n_estimators=500)  # 集成500个子分类器

ada_clf.fit(X_train, y_train)
AdaBoostClassifier(algorithm='SAMME.R',
          base_estimator=DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=2,
            max_features=None, max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, presort=False, random_state=None,
            splitter='best'),
          learning_rate=1.0, n_estimators=500, random_state=None)
ada_clf.score(X_test, y_test)
0.856

Gradient Boosting

  • 训练模型m1,产生错误e1
  • 针对e1训练模型m2,产生错误e2
  • 针对e2训练模型m3, 产生错误e3......
  • 最终预测结果是:m1+m2+m3...
gboosting.png
from sklearn.ensemble import GradientBoostingClassifier
# Gradient Boosting就是以决策树为基础的,不需要写,设好集成子模型数量就行
gb_clf = GradientBoostingClassifier(max_depth=2, n_estimators=30)
gb_clf.fit(X_train, y_train)
GradientBoostingClassifier(criterion='friedman_mse', init=None,
              learning_rate=0.1, loss='deviance', max_depth=2,
              max_features=None, max_leaf_nodes=None,
              min_impurity_decrease=0.0, min_impurity_split=None,
              min_samples_leaf=1, min_samples_split=2,
              min_weight_fraction_leaf=0.0, n_estimators=30,
              presort='auto', random_state=None, subsample=1.0, verbose=0,
              warm_start=False)
gb_clf.score(X_test, y_test)
0.912

其他常用Boosting算法实现:XGboost,GBDT;

sklearn不带,需要另行安装

Boosting 解决回归问题子库

from sklearn.ensemble import AdaBoostRegressor
from sklearn.ensemble import GradientBoostingRegressor
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,780评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,424评论 1 305
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,397评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,576评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,997评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,945评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,107评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,850评论 0 208
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,625评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,804评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,285评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,613评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,291评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,164评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,963评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,096评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,886评论 2 278

推荐阅读更多精彩内容