集成学习——BAGGING和随机森林

集成学习——BAGGING和随机森林

1、什么是集成学习

  首先,我们看一下什么是集成学习。“三个臭皮匠,顶个诸葛亮”,这句话大家都听过吧,实际上,集成学习的思想就是:
  将若干个学习器(分类器、回归器)组合之后产生一个新的学习器。
  这里你要了解一个概念:弱学习器(weak learner)

  • 弱学习器,就是分类准确率只稍微好于随机猜测的分类器。
      这样的学习器精度不是特别的好,比如我们之前学到的KNN,逻辑回归啊什么的,那些基础的学习模型,都是一些弱学习器。

重点:集成学习最基础的要求
集成算法的成功在于保证弱分类器的多样性
  集成学习,重点就是要保证组成新学习器所用弱学习器的多样新和差异性,因为如果你所用的弱学习器都是一样的,那组合起来就没有意义了呀。
  而且集成不稳定的算法,也能得到一个比较明显的性能提升。
  下面我们用这样一个例子来具体看一看
在这里插入图片描述
  现在我做一个分类预测模型,我首先设计了最上层的3个弱的分类模型,三个模型的分类边界是不同的,我们拿分类边界的一个样本来做例子,假如:分类边界上的一个样本,在第一个模型中杯预测为三角,在第二个模型中杯预测为圆,在第三个模型中被预测为三角,那么最后为我们就可以将这三个模型融合合在一起,产生一个新的分类边界,最后的结果我们用多数表决法,最后杯预测为三角。

常见的集成学习思想:

  • Bagging思想
    • 重点阐述Bagging思想下的随机森林RF
  • Boosting思想
    • Adaboost
    • GBDT系列
      • XGB
      • LightGBM
          这两个实际上是对GBDT算法的优化
  • Stacking思想
      实际上是一种模型融合的思想,虽然有些情况下缺失对效果的评估有一定的提升,但是由于模型过多,在效率上会有一定的成本,所以只在比赛中用的比较多

  好了上边就是对集成学习的大致阐述,集成学习的经典思想后面的文章我会一一更新,我们慢慢来。接下来就让我们正是进入集成学习。


2、怎样进行集成学习

  1. 弱分类器间存在一定的差异性这会导致分类的边界不同,也就是说弱学习器可能存在错误。那么将多个弱分类器合并后,就可以得到更加合理的边界,减少整体的错误率,实现更好的效果

补充:从哪些角度使得若学习器之间形成差异性呢? 假如我现在有1000条标注好的数据。
可以这样:
1、(从算法本身去考虑)使用不同的算法模型。
  比如我第一个用KNN,第二个用Logistic,第三个用DT。
2、(从数据层面考虑)如果我现在告诉你只能用Logistic呢?
  因为算法本身,对于不同的数据就会训练出不同的学习效果啊。

  1. 对于数据集过大或者过小,可以分别进行划分有放回采样的操作产生不同的数据子集,然后使用数据子集训练不同的分类器,最终再合并成为一个大的分类器

数据的采集方式也有两种,我们还是以100万条数据和1万条数据为例:
数据集过大:
1、划分,划分成10等份,每一份数据训练一个弱学习器。
2、有放回的随机采样10万条进行弱学习器的训练。
数据集过小
1、如果数据集过小,只有1万条数据,我有放回的抽样,抽1万条出来,这样每次抽到的都是不同的数据,就保证了数据集之间的差异性,从而训练得到了不同的弱学习器,实现了学习器之间的差异性

  1. 如果数据的划分边界过于复杂,使用线性模型很难描述情况,那么可以训练多个模型,然后再进行模型的融合
  2. (数据集本身就不一样的情况)对于多个异构的特征集的时候,很难进行融合,那么可以考虑每个数据集构建一个分类模型,然后将多个模型融合。

补充
实际上集成学习还可以解决样本不均衡的问题
  现在有10万条样本,假设有9万个0类别,1万个1类别,这个时候样本之间是不均衡的,我们怎么办?
  1、fit(X,Y,class_weight)模型训练的时候设置参数class_weight,给数据少的类别添加大一点的权重,在训练的时候做种关注这样样本的特征属性。
  利用集成学习的思想,构造多组数据集,第一组数据集1万个0,8千个1,这样采取对组数据集,然后训练多个学习器,最后组成一个大的学习器进行预测。从而解决样本不均衡的问题。

知道了什么是集成学习,也了解了为啥要进行集成学习,怎样进行集成学习,接下来我们就逐个分析集成学习的经典算法思想。


3、Bagging方法

Bagging是训练通过构造数据的差异性,从而保重弱学习器的差异性

下面这些是Bagging思想的关键:

  • Bagging方法又叫做自举汇聚法(Bootstrap Aggregating),思想是:在原始数据集上通过有放回的抽样的方式,重新选择出S个新数据集来分别训练S个分类器的集成技术
  • Bagging方法训练出来的模型在预测新样本分类/回归的时候,会使用多数投票或者求均值的方式来统计最终的分类/回归结果
  • Bagging方法的弱学习器可以是基本的算法模型,eg: Linear、Ridge、Lasso、Logistic、Softmax、ID3、C4.5、CART、SVM、KNN等。
  • Bagging方式是有放回的抽样,并且每个子集的样本数量必须和原始样本数量一致,所以抽取出来的子集中是存在重复数据的,模型训练的时候允许存在重复数据
  • 差不多有1/3的样本数据是不在Bagging的每个子模型的训练数据中的。
    在这里插入图片描述

公式理解:
每一次,每一条数据被抽到的概率都是m分之1,不被抽到的就是1减m分之一,那现在我抽取m次,每一次都没有被抽到的概率就是1减m分之1的m次方,他的极限就是e分之1.

4、Bagging方法训练、预测过程

这里用用这个图片来理解下更直观:
训练:
在这里插入图片描述
  S次有放回重采样,生成S个数据集,训练S个学习器,最后形成强学习器

预测:
在这里插入图片描述
  通过每个弱学习器都会产生一个预测结果,然后我们通过多数投片或者求平均值的方式得到最终的预测结果。

5、Bagging方法代码实现

  这里我们依然调用sklearn库中的类进行实现。这里实现的是一个回归任务的集成学习模型
  因为我们在训练的时候要涉及到数据的有放回的采样,我们来复习一下采样的操作。使用pandas模块下的sample方法。

import pandas as pd
#数据
df = pd.DataFrame([[1, 5.56], [2, 5.7], [3, 5.91], [4, 6.4], [5, 6.8],
                   [6, 7.05], [7, 8.9], [8, 8.7], [9, 9], [10, 9.05]], columns=['X', 'Y'])

dfsample = df.sample(frac=1.0,replace=False)
print(dfsample)
print(dfsample.shape)
"""
sample() 抽样
参数:
    n=None,  抽样数据的条数
    frac=None, 抽样的比例
    replace=False, 是否有放回抽样
    weights=None, 权重
    random_state=None, 随机数种子
    axis=None 维度
"""
#对采样数据去重操作
df01 = dfsample.drop_duplicates()
print(df01)
print(df01.shape)

  下面是集成分类器和单一分类器预测结果进行比较,注意看代码注释

# 课程内容:
# 开发时间: 21:21
"""
bagging 回归
"""
import pandas as pd
import numpy as np
from sklearn.tree import DecisionTreeRegressor#回归树包,为了实现基础的弱学习器,这里我们用决策树作为弱学习器
from sklearn.metrics import r2_score
###数据,这里是一个线性数据,一个pandas中的DataFrames
df = pd.DataFrame([[1, 10.56],
                   [2, 27],
                   [3, 39.1],
                   [4, 40.4],
                   [5, 58],
                   [6, 60.5],
                   [7, 79],
                   [8, 87],
                   [9, 90],
                   [10, 95]],
                  columns=['X', 'Y'])
M = []#用来存储弱学习器
n_trees = 100 #定义要构建的弱学习器的数量

#循环构建弱学习器
for i in range(n_trees):
    #对原始数据有放回的抽样抽M次(m有多少数据就抽多少次)
    tmp = df.sample(frac=1.0,replace=True)#有放回的抽取与样本集相同个数的样本,注意此处不需要设置随机数种子,否则每次抽取的数据又一样了
    #对抽取的数据进行特征和便签的分类
    X = tmp.iloc[:,:-1]
    Y = tmp.iloc[:,-1]
    #每次循环构建一颗深度为1的决策树
    model = DecisionTreeRegressor(max_depth=1)
    #对每一课决策树进行训练
    model.fit(X,Y)
    #将训练好的决策树添加到弱学习器存储列表
    M.append(model)


#做预测
x = df.iloc[:,:-1]
y = df.iloc[:,-1]
#创建一颗决策树用于对比
model01 = DecisionTreeRegressor(max_depth=1)
model01.fit(x,y)
#预测结果
y_hat_01 = model01.predict(x)#predict返回的是样本的预测值,predict_proba返回的是n行k列的数组,第行代表一个样本,第j列代表预测为这一类别的gaulv

print(y_hat_01)
print(model01.score(x,y))#输出上面单棵树预测的准确率
print('-'*100)
res = np.zeros(df.shape[0])#用于存储每个弱学习器器对每个样本最后的预测值
#循环取出每一个弱分类器
for j in M:
    res += j.predict(x)#将所有弱学习器类器的预测值对应相加
y_hat = res/n_trees#利用求平均值的方法求出最后的预测值
print(y_hat)
print('R2',r2_score(y,y_hat))#R方,将预测值跟只使用均值的情况下相比,看能好多少。其区间通常在(0,1)之间。模型越好:r2→1,模型越差:r2→0

  输出结果,可以看到,用了集成学习以后的模型预测的更加细,有多个值,在准确率上也更好
在这里插入图片描述
  至于分类模型的实现,我现在不太想码了,有需要的评论区提取把。


6、随机森林(Random Forest)

  实际上,随机森林是在Bagging策略的基础上进行修改后的一种算法。

  随机森林的算法步骤如下:

  1. 从原始样本集(m个样本)中用Bootstrap采样(有放回重采样) 选出m个样本;
  2. 使用抽取出来的子数据集(存在重复数据)来训练决策树;从所有属性中随机选择K个属性,从K个属性中选择出最佳分割属性作为当前节点的划分属性,按照这种方式来迭代的创建决策树。

我们正常构建决策树的时候,我们分割的时候是度量所有属性划分纯度选择最优的属性进行划分。

  1. 重复以上两步S次,即建立S棵决策树
  2. 这S个决策树形成随机森林,通过投票表决结果决定数据属于那一类

注意他和Banging+决策树不一样,他不仅对数据做随机选择,对划分属性也进行随机选择。在构建的时候,就是把Bangging+决策树在构建每一个弱学习器的时候把splitter参数置为random
相同点是:每一课决策树都不一样

doc = DocisionTreeClassifier(max_depth=1,splitter='random',max_feature=k)#随机抽入k个特征属性进行分割构建决策树

看一下图,更直观的对比一下随机森林和决策树构建的不同

在这里插入图片描述


7、RF推广算法

  RF算法在实际应用中具有比较好的特性,应用也比较广泛,主要应用在:分类、回归、特征转换、异常点检测等。常见的RF变种算法如下:

  • Extra Tree(分类,回归)
  • Totally Random Trees Embedding(TRTE)(特征转换)
  • Lsolation Forest(异常点检测)

特征转换:
1、亚编码One-Hot
2、标准化,归一化
3、多项式拓展等等

7.1 Extra Tree

  首先你要确定Extra Tree是RF的一种变种,那就是他也是随机抽入K个特征来迭代构建决策树,不同点在于:

  • RF会随机重采样来作为子决策树的训练集,而Extra Tree每个子决策树采月原始数据集训练;
  • RF在选择划分特征点的时候会和传统决策树一样,会基于信息增益、信息增益率、基尼系数、均方差等原则来选择最优特征值;而Extra Tree会随机的选择一个特征值来划分决策树。

也就是说,在构建弱学习器的时候,没有保证数据上的差异,那就要保证构建的树上的差异,所以Extra Tree算法构建数的时候,进行划分特征的选择是随机选择。不再是通过划分后纯度的度量。什么信息熵啊,错误率就不考虑了。

  Extra Tree因为是随机选择特征值的划分点,这样会导致决策树的规模一般大于RF所生成的决策树。也就是说Extra Tree模型的方差相对于RF进一步减少。在某些情况下,Extra Tree的泛化能力比RF的强。

因为我们在传统的决策树构建中也曾说过,即便是不进行纯度的度量随机选择属性进行分割,最后也能构建一颗100%准确的决策树,就是数的广度,深度会很大,而且容易发生过拟合。

7.2 Totally Random Trees Embedding(TRTE)

  对这个算法,你不要把它当成一种任务模型算法,就把他当成和:多项式拓展一样的数据转换方式。

  1. TRTE是一种非监督数据转化方式。将低维的数据集映射到高维,从而让映射到高维的数据更好的应用于分类回归模型。
  2. TRTE算法的转换过程类似RF+KDTree算法的方法,建立T个决策树来拟合数据(是类似KD-Tree一样基于特征属性的方差选择划分特征)。当决策树构建完成后,数据集里的每个数据在T个决策树中叶子节点的位置就定下来了,将位置信息转换为向量就完成了特征转换操作。
  3. ·案例:有3棵决策树,各个决策树的叶子节点数目分别为:5,5,4,某个数据x划分到第一个决策树的第3个叶子节点,第二个决策树的第一个叶子节点,第三个决策树的第四个叶子节点,那么最终的x映射特征编码为:(0,0,1,0,0,1,0,0,0,0,0,0,0,1)

在这里插入图片描述

  如果我们现在只有X可不可以构建决策树?
  当然可以,就是我们之前构建的KD-Tree,我们在构建他的时候,按照特征属性的方差进行选择,选择方差最大的属性进行划分,作为最上层的节点。现在我们结合RF的思想,对数据集有放回的重采样,那么构建出来的T棵决策树肯定就不一样了啊
  当有一条新的数据x_new进来以后,进入每一条决策树都会落在不同的叶子结点,我们对不同位置的叶子节点进行编码,最后,就所有的位置向量整合在一起形成一个新的特征编码,就起到了特征转换的操作,进行了升维,比如一开始我只有3个特征属性,每个特征属性有1个比特位表示,经过每一课树以后转换成了5位,5位,和者4位的位置向量信息,然后将所有树的位置向量信息加在一起,最后就是5+5+34= 14位的特征是不是升维了。如上图.
整个过程就是把每一条数据经过每一课树都转换成了更高位的特征空间,最后又整合在一起,维度更高了。

对于数据的升维方式
1、多项式拓展
2、TRTE特征升维

7.3 Lsolation Forest(IForest)

  也是同TRTE一样,是对数据做处理的算法

  • lForest是一种异常点检测算法,使用类似RF的方式来检测异常点; lForest算法和RF算法的区别在于:
    • 1.在随机采样的过程中,一般只需要少量数据即可;
    • 2.在进行决策树构建过程中,lForest算法会随机选择一个划分特征并对划分特征随机选择一个划分阈值;
    • 3.lForest算法构建的决策树一般深度max_depth是比较大的。
  • 区别原因:目的是异常点检测,所以只要能够区分异常的即可,不需要大量数据;

解释:
  当有一条新的数据x_new进来以后,通过每一课决策树,落到多个叶子结点,对于通过某一课树来说,落到节点的深度越浅,说明这可节点有可能是离群点,因为他在这棵树种只经过一个特征的判断,就被分出去了,然后经过多棵决策树,如果他在多棵决策树都落在了比较浅的节点,那就说明他是异常点特征。

  具体怎么计算?
  对于异常点的判断,则是将测试样本x拟合到m棵决策树上。计算在每棵树上该样本的叶子节点的深度ht(x)。从而计算出平均深度h(x);然后就可以使用下列公式计算样本点x的异常概率值,p(s,m)的取值范围为[0,1],越接近于1,则是异常点的概率越大。备注:如果落在的叶子节点为正常样本点,那么当前决策树不考虑,(因为在很多落得不比较浅,有几个落得比较的,那么落得比较的的树就不考虑了)如果所有决策树上都是正常样本点,那么直接认为异常点概率为0。

在这里插入图片描述

c(m):m确定的强狂下,这个值就是一个常数


8、RF随机森林总结

  • RF主要优点:

    • 1.训练可以并行化(每一个弱学习器器之间是相互独立的),对于大规模样本的训练具有速度的优势;
    • 2由于进行随机选择决策树划分特征列表,这样在样本维度比较高的时候,仍然具有比较高的训练性能;
    • 3.给以给出各个特征的重要性列表;
    • 4.由于存在随机抽样,训练出来的模型方差小,泛化能力强,能够缓解过拟合的情况;.
    • 5.RF实现简单;
    • 6.对于部分特征的缺失不敏感。
  • RF主要缺点:

    • 1.在某些噪音比较大的特征上(数据特别异常情况),RF模型容易陷入过拟合;
    • 2取值比较多的划分特征对RF的决策会产生更大的影响,从而有可能影响模型的效果。

9、RF 在 scikit-learn中相关参数

作为“调包侠”要了解下列调包参数哈。
氛围分类任务和回归任务:
在这里插入图片描述

9.1 RF简单案例sklearn实现

import pandas as pd
import numpy as np
import sys
# from sklearn.preprocessing import Imputer
from sklearn.impute import SimpleImputer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, MinMaxScaler  ##标准化,归一化
from sklearn.decomposition import PCA
from sklearn.model_selection import GridSearchCV

pd.set_option("display.max_columns", None)

##读取数据
datas = pd.read_csv('./datas/risk_factors_cervical_cancer.csv', sep=',')
# print(datas.head())
# print(datas.info())
names = datas.columns
# print(names)
# sys.exit()
###数据清洗
datas.replace('?', np.nan, inplace=True)
# print(datas.info())
# sys.exit()
# print(datas.head())
###使用Imputer进行缺省值的填充 列填充
# imputer = Imputer(missing_values='NaN', strategy='mean', axis=0)
imputer = SimpleImputer()
datas = imputer.fit_transform(datas)
datas = pd.DataFrame(datas, columns=names)
# print(datas.head())
# print(datas.info())

###获取特征属性X 和目标属性Y
X = datas.iloc[:, :-4]
Y = datas.iloc[:, -4:].astype('int')
# print(X.info())
# print(Y.info())

###数据分割
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=10)

###构建一个管道
###数据标准化,数据归一化 (数据量纲) 决策树来说我们其实不需要做这个操作
##标准化:把数据转化为均值为0,方差为1的
##归一化:把数据压缩到0-1

###PCA降维
models = [Pipeline([('standarscaler', StandardScaler()),
                    ('pca', PCA()),
                    ('RF', RandomForestClassifier())]),
          Pipeline([
              ('pca', PCA(n_components=0.5)),
              ('RF', RandomForestClassifier(n_estimators=50, max_depth=1))])
          ]
'''
###设置参数
params = {'pca__n_components':[0.5,0.6,0.7,0.8,0.9],
          'RF__n_estimators':[50,100,150],
          'RF__max_depth':[1,3,5,7]}
##网格调参
model = GridSearchCV(estimator=models[0],param_grid=params,cv=5)
##训练
model.fit(x_train,y_train)
print('最优参数:',model.best_params_)
print('最优模型:',model.best_estimator_)
print('最优模型的分数:',model.best_score_)
'''

model = models[1]
model.fit(x_train, y_train)
print(model.score(x_train, y_train))
print(model.score(x_test, y_test))

# ###保存模型
# from sklearn.externals import joblib
# joblib.dump(model,'./model/risk01.m')

训练集测试集正确率都到到了0.8以上
在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

企鹅家的北极熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值