集成算法Ensemble Method

集成学习将多个学习器通过某种策略集合成一个强学习器,根据个体学习器间是否存在依赖关系分为【boosting系列算法】【个体学习器间存在强依赖关系】和【bagging、随机森林系列算法】【个体学习器间不存在强依赖关系】。

stacking?

一、Boosting算法

Boosting算法是将“弱学习算法”提升为“强学习算法“的过程,主要思想是”三个臭皮匠顶个诸葛亮“,Boosting算法涉及两个部分,加法模型和向前分步算法。前向分步算法用来推导弱学习器的系数\alpha_m

\alpha_m推导过程参考:https://www.baidu.com/link?url=q9NaQkJvcmxSXdjmnFswY_aCRkgdEBBsddIFt690Hh7-_ghCwEzR31wipHvcB4sfrbxUkN5V76TxuNgD-sovLK&wd=&eqid=9724a66600003ad4000000065e8d4bd2

1.1 Adaboost

Adaboost是一种迭代算法,通过构造多个弱分类器,然后把这些弱分类器集合起来构成一个更强的最终分类器。Adaboost提供的是一种框架。它可以使用各种来构造弱分类器,比如使用单决策树作为弱分类器。

1.1.1 Adaboost分类问题:

在分类问题中有SAMME和SAMME.R两种算法,SAMME.R收敛速度更快

SAMME算法流程:

输入训练数据集T=\left\{\left(x_{1}, y_{1}\right),\left(x_{2}, y_{2}\right),\left(x_{N}, y_{N}\right)\right\}, x_{i} \in X \subseteq R^{n}, y_{i} \in Y=-1,1

(1)初始化样本的权值分布:D_{1}=\left(w_{11}, , w_{12}, \dots, w_{1i}\right), w_{1i}=\frac{1}{N}, i=1,2, \dots, N

(2)对m个弱分类器,m=1,2,...,M:

       a)使用具有权值分布D_m的训练数据集进行学习,得到基本分类器G_m(x),其输出值为{-1,1};

       b)计算弱分类器在训练器数据集上的分类误差率,其值越小的基分类器在最终分类器中的作用越大。

         e_{m}=P\left(G_{m}\left(x_{i}\right) \neq y_{i}\right)=\sum_{i=1}^{N} w_{m i} I\left(G_{m}\left(x_{i}\right) \neq y_{i}\right),其中I\left(G_{m}\left(x_{i}\right) \neq y_{i}\right)取值为0或1,取0表示分类正确,取1表示分类错误。

         c)计算弱分类器G_{m}\left(x\right)在强分类器中所占权重:\alpha_{m}=\frac{1}{2} \ln \frac{1-e_{m}}{e_{m}}

         d)更新训练数据集的样本权值分布

                            \begin{array}{l} D_{m+1}=\left(w_{m+1,1}, w_{m+1,2} \cdots w_{m+1, i} \cdots, w_{m+1, N}\right) \\ w_{m+1, i}=\frac{w_{m i}}{Z_m} \exp \left(-\alpha_{m} y_{i} G_{m}\left(x_{i}\right)\right), i=1,2, \cdots, N \end{array}

                    其中,Z_{m}是规范化因子,主要作用是将的值规范化到0-1之间,使得\sum_{i=1}^{N} w_{m i}=1

                            Z_{m}=\sum_{i=1}^{N} w_{m i} \exp \left(-\alpha_{m} y_{i} G_{m}\left(x_{i}\right)\right)

                   从权重的更新表达式可以看出,当分类正确时会得到比较小的更新权值,分类错误时,会得到比较大更新的权值。

(3)利用加权平均法构建基本分类器的线性组合:f(x)=\sum_{m=1}^{M} \alpha_{m} G_{m}(x)\right

      得到最终强分类器:

G(x)=\operatorname{sign}(f(x))=\operatorname{sign}\left(\sum_{m=1}^{M} \alpha_{m} G_{m}(x)\right)

SAMME.R算法流程:

(1)初始化样本的权值分布:D_{1}=\left(w_{11}, , w_{12}, \dots, w_{1i}\right), w_{1i}=\frac{1}{N}, i=1,2, \dots, N

(2)对m个弱分类器,m=1,2,...,M:

        (a)使用带有权重的样本来训练一个弱学习器G_m(x)

        (b)获得带有权重分类的概率评估:P_{m k}\left(x_{i}\right)=\operatorname{Prob}_{w}\left(c=k | x_{i}\right),其中P_{m k}\left(x_{i}\right)表示第m个弱学习器把样本x_i分为第k类的               概率,k=1,2,...,K。

        (c)使用加权概率推导出加法模型的更新,然后将其应用于数据:    

                                   h_{m k}(x)=(K-1)\left(\log P_{m k}(x)-\frac{1}{K} \sum_{k=1}^{K} \log P_{m \bar{k}}(x)\right),k=1,2,...,K

        (d)更新样本点权重系数:w_{m+1, i}=w_{m i} \exp \left(-\frac{K-1}{K} y_{i} \log P_{m}\left(x_{i}\right)\right)

        (e)标准化样本点权重w

(3)得到最终的强分类器:

G(x)=\operatorname{sign}\left(\operatorname{argmax}_{K} \sum_{m=1}^{M} h_{m k}(x)\right),表示使\sum_{m=1}^{M} h_{m k}(x)最大的K就是所预测的结果。

sklearn库中AdaBoost参数设置:https://www.cnblogs.com/pinard/p/6136914.html#!comments

import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import AdaBoostClassifier
#这里采用分类树作为基分类器
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_gaussian_quantiles
X1,y1=make_gaussian_quantiles(cov=2.0,n_samples=500,n_features=2,n_classes=2,random_state=1)
X2,y2=make_gaussian_quantiles(mean=(3,3),cov=1.5,n_samples=400,n_features=2,n_classes=2,random_state=1)
X=np.concatenate((X1,X2))
y=np.concatenate((y1,-y2+1))


bdt=AdaBoostClassifier(DecisionTreeClassifier(max_depth=2,min_samples_split=20,min_samples_leaf=5),algorithm="SAMME",n_estimators=200,learning_rate=0.8)
bdt.fit(X,y)
x_min,x_max=X[:,0].min()-1,X[:,1].max()+1
y_min,y_max=X[:,1].min()-1,X[:,1].max()+1
xx,yy=np.meshgrid(np.arange(x_min,x_max,0.02),np.arange(y_min,y_max,0.02))
Z=bdt.predict(np.c_[xx.ravel(),yy.ravel()])
Z=Z.reshape(xx.shape)
cs=plt.contourf(xx,yy,Z,cmap=plt.cm.Paired)
plt.scatter(X[:,0],X[:,1],c=y,marker='o')
plt.show()
print(bdt.score(X,y))

1.1.2AdaBoost回归问题:

算法流程:

(1)初始化样本的权值分布:D_{1}=\left(w_{11}, , w_{12}, \dots, w_{1i}\right), w_{1i}=\frac{1}{N}, i=1,2, \dots, N

(2)对m个弱分类器,m=1,2,...,M:

          (a)使用具有权值分布D_m的训练数据集进行学习,得到弱分类器G_m(x)

          (b)计算训练集上的最大误差:E_{k}=\max \left|y_{i}-G_{m}\left(x_{i}\right)\right|, i=1,2, \dots, N

          (c)计算每个样本点的相对误差:

          如果是线性误差:e_{m i}=\frac{\left|y_{i}-G_{m}\left(x_{i}\right)\right|}{E_{m}}

          如果是平方误差:e_{m i}=\frac{\left(y_{i}-G_{m}\left(x_{i}\right)\right)^{2}}{E_{m}^{2}}

          如果是指数误差:e_{m i}=1-\exp \left(\frac{-\left|y_{i}-G_{m}\left(x_{i}\right)\right|}{E_{m}}\right)

          (d)计算回归误差率:e_m=\sum_{i=1}^Nw_{mi}e_{mi}

          (e)计算弱学习器系数:\alpha_m=\frac{e_m}{1-e_m}

          (f)更新样本权重分布:w_{m+1,i}=\frac{w_{mi}}{Z_m}\alpha_m^{1-e_{mi}},其中Z_m是规范化因子,Z_m=\sum_{i=1}^Nw_{mi}\alpha_m^{1-e_{mi}}

(3)得到强学习器

G(x)=\sum_{m=1}^Mg(x)ln\frac{1}{\alpha_m},其中g(x)是所有\alpha_mG_m(x)的中位数(m=1,2,...,M)

1.1.3 AdaBoost优缺点:

优点:

(1)分类精度很高

(2)不容易发生过拟合

(3)在AdaBoost框架下,可以使用各种模型来构建弱学习器

(4)参数少,不需要调节太多参数

缺点:

(1)对异常样本敏感,异常样本在迭代中可能会获得较高的权重,影响最终的强学习器的预测准确性

(2)弱分类器数目不太好设定,可以使用交叉验证来进行确定

(3)数据不平衡导致分类精度下降

(4)训练比较耗时,每次重新选择当前分类器最好切分点

 

1.2、GBDT(算法提升梯度树)

GBDT通过多伦迭代,每轮迭代产生一个弱学习器,每个学习器都是在上一轮学习器的残差基础上进行训练。GBDT的弱学习器采用的是回归树。

GBDT回归算法:输入训练集T=\left \{ (x_1,y_1),(x_2,y_2),...,(x_m,y_m) \right \},T为最大迭代次数,m为样本个数,损失函数L。

(1)初始化弱学习器:f_{0}(x)=\underbrace{\arg \min }_{c} \sum_{i=1}^{m} L\left(y_{i}, c\right)

(2)对迭代次数t=1,2,...,T有:

           (a)对样本i=1,2,...,m,计算负梯度:r_{t i}=-\left[\frac{\left.\partial L\left(y_{i}, f\left(x_{i}\right)\right)\right)}{\partial f\left(x_{i}\right)}\right]_{f(x)=f_{t-1}(x)}

           (b)利用(x_i,r_{ti})(i=1,2,...,m)拟合一颗CART回归树,得到第t棵回归树,其对应的叶子节点区域为R_{tj},j=1,2,...,J。其中J为回归树t叶子节点的个数。

           (c)对叶子区域j=1,2,...,J,计算最佳拟合值:c_{t j}=\underbrace{\arg \min }_{c} \sum_{x_{i} \in R_{t j}} L\left(y_{i}, f_{t-1}\left(x_{i}\right)+c\right)

           (d)更新强学习器:f_{t}(x)=f_{t-1}(x)+\sum_{j=1}^{J} c_{t j} I\left(x \in R_{t j}\right)

(3)得到强学习器f(x)的表达式:f(x)=f_{T}(x)=f_{0}(x)+\sum_{t=1}^{T} \sum_{j=1}^{J} c_{t j} I\left(x \in R_{t j}\right)

参考资料:https://www.cnblogs.com/pinard/p/6140514.html(还讲了GDBT的分类算法步骤,用于分类时和回归的思路一样,只是损失函数不同)

实例参考:https://blog.csdn.net/zpalyq110/article/details/79527653

import pandas as pd
import numpy as np
from sklearn.ensemble import GradientBoostingClassifier
from sklearn import cross_validation,metrics
from sklearn.grid_search import GridSearchCV
import matplotlib.pyplot as plt
train=pd.read_csv('train_modified.csv')
train['Disbursed'].value_counts()
target='Disbursed'
IDcol='ID'
x_columns = [x for x in train.columns if x not in [target, IDcol]]
X=train[x_columns]
y=train['Disbursed']
#先不设置任何参数
gbm0=GradientBoostingClassifier(random_state=10)
gbm0.fit(X,y)
y_pred=gbm0.predict(X)
y_predprob=gbm0.predict_proba(X)[:,1]
print('Accuracy:%.4g'%metrics.accuracy_score(y.values,y_pred))
print('AUC Score (tain):%f'%metrics.roc_auc_score(y,y_predprob))


#通过网格搜索进行调参
param_test1 = {'n_estimators':list(range(20,81,10))}
gsearch1 = GridSearchCV(estimator = GradientBoostingClassifier(learning_rate=0.1, min_samples_split=300,
                                  min_samples_leaf=20,max_depth=8,max_features='sqrt', subsample=0.8,random_state=10), 
                       param_grid = param_test1, scoring='roc_auc',iid=False,cv=5)
gsearch1.fit(X,y)
gsearch1.grid_scores_, gsearch1.best_params_, gsearch1.best_score_

param_test2 = {'max_depth':list(range(3,14,2)),'min_samples_split':list(range(100,801,200))}
gsearch2 = GridSearchCV(estimator = GradientBoostingClassifier(learning_rate=0.1, n_estimators=60,
                                  min_samples_leaf=20,max_features='sqrt', subsample=0.8,random_state=10), 
                       param_grid = param_test2, scoring='roc_auc',iid=False,cv=5)
gsearch2.fit(X,y)
gsearch2.grid_scores_, gsearch2.best_params_, gsearch2.best_score_

GBDT代码调参:https://www.cnblogs.com/pinard/p/6143927.html

1.3、XGboost

XGboost是GBDT的一种高效实现,XGboost相对于GBDT来说,在损失函数后加了一项正则项\Omega\left(h_{t}\right)=\gamma J+\frac{\lambda}{2} \sum_{j=1}^{J} w_{t j}^{2}L_{t}=\sum_{i=1}^{m} L\left(y_{i}, f_{t-1}\left(x_{i}\right)+h_{t}\left(x_{i}\right)\right)+\gamma J+\frac{\lambda}{2} \sum_{j=1}^{J} w_{t j}^{2},其中w_{tj}代表第j个叶子节点的最优值。要求损失函数的最小值,XGBoost采用泰勒二次展开式求解:

\begin{aligned} L_{t} &=\sum_{i=1}^{m} L\left(y_{i}, f_{t-1}\left(x_{i}\right)+h_{t}\left(x_{i}\right)\right)+\gamma J+\frac{\lambda}{2} \sum_{j=1}^{J} w_{t j}^{2} \\ & \approx \sum_{i=1}^{m}\left(L\left(y_{i}, f_{t-1}\left(x_{i}\right)\right)+\frac{\partial L\left(y_{i}, f_{t-1}\left(x_{i}\right)\right.}{\partial f_{t-1}\left(x_{i}\right)} h_{t}\left(x_{i}\right)+\frac{1}{2} \frac{\partial^{2} L\left(y_{i}, f_{t-1}\left(x_{i}\right)\right.}{\partial f_{t-1}^{2}\left(x_{i}\right)} h_{t}^{2}\left(x_{i}\right)\right)+\gamma J+\frac{\lambda}{2} \sum_{j=1}^{J} w_{t j}^{2} \end{aligned}

把第i个样本在第t个弱学习器的一阶导和二阶导分别记为:

g_{t i}=\frac{\partial L\left(y_{i}, f_{t-1}\left(x_{i}\right)\right.}{\partial f_{t-1}\left(x_{i}\right)}, h_{t i}=\frac{\partial^{2} L\left(y_{i}, f_{t-1}\left(x_{i}\right)\right.}{\partial f_{t-1}^{2}\left(x_{i}\right)}

此时损失函数表示为:

L_{t} \approx \sum_{i=1}^{m}\left(L\left(y_{i}, f_{t-1}\left(x_{i}\right)\right)+g_{t i} h_{t}\left(x_{i}\right)+\frac{1}{2} h_{t i} h_{t}^{2}\left(x_{i}\right)\right)+\gamma J+\frac{\lambda}{2} \sum_{j=1}^{J} w_{t j}^{2}

损失函数中第一项和最小化无关,可以去掉,由于每个决策树的第j个叶子节点的取值最终会是同一个值w_{tj},因此损失函数可简化为:

\begin{aligned} L_{t} &\left.\approx \sum_{i=1}^{m} g_{t i} h_{t}\left(x_{i}\right)+\frac{1}{2} h_{t i} h_{t}^{2}\left(x_{i}\right)\right)+\gamma J+\frac{\lambda}{2} \sum_{j=1}^{J} w_{t j}^{2} \\ &=\sum_{j=1}^{J}\left(\sum_{x_{i} \in R_{t} j} g_{t i} w_{t j}+\frac{1}{2} \sum_{x_{i} \in R_{t} j} h_{t i} w_{t j}^{2}\right)+\gamma J+\frac{\lambda}{2} \sum_{j=1}^{J} w_{t j}^{2} \\ &=\sum_{j=1}^{J}\left[\left(\sum_{x_{i} \in R_{t j}} g_{t i}\right) w_{t j}+\frac{1}{2}\left(\sum_{x_{i} \in R_{t} j} h_{t i}+\lambda\right) w_{t j}^{2}\right]+\gamma J \end{aligned}

把每个叶子节点区域样本的一阶和二阶导数表示为:

G_{t j}=\sum_{x_{i} \in R_{i j}} g_{t i}, H_{t j}=\sum_{x_{i} \in R_{i j}} h_{t i}

最终损失函数表示为:

L_{t}=\sum_{j=1}^{J}\left[G_{t j} w_{t j}+\frac{1}{2}\left(H_{t j}+\lambda\right) w_{t j}^{2}\right]+\gamma J

损失函数对w_{tj}求导等于0可以得到叶子节点区域的最优解为:

w_{tj}=-\frac{G_{tj}}{H_{tj}+\lambda},将期代入损失函数得到:L_{t}=-\frac{1}{2} \sum_{j=1}^{J} \frac{G_{t j}^{2}}{H_{t j}+\lambda}+\gamma J

在对树进行分裂时,期望分裂后的损失函数值比分裂前小很多,假设分裂后左右子树的一阶二阶导数和为G_L,H_L,G_R,H_R

则我们期望下式最大:

-\frac{1}{2} \frac{\left(G_{L}+G_{R}\right)^{2}}{H_{L}+H_{R}+\lambda}+\gamma J-\left(-\frac{1}{2} \frac{G_{L}^{2}}{H_{L}+\lambda}-\frac{1}{2} \frac{G_{R}^{2}}{H_{R}+\lambda}+\gamma(J+1)\right)

整理后为:\max \frac{1}{2} \frac{G_{L}^{2}}{H_{L}+\lambda}+\frac{1}{2} \frac{G_{R}^{2}}{H_{R}+\lambda}-\frac{1}{2} \frac{\left(G_{L}+G_{R}\right)^{2}}{H_{L}+H_{R}+\lambda}-\gamma

算法流程:

#使用原生的API接口
import numpy as np
import pandas as pa
import matplotlib.pyplot as plt
import xgboost as xgb
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.datasets.samples_generator import make_classification
from sklearn.metrics import accuracy_score

X,y=make_classification(n_samples=10000,n_features=20,n_redundant=0,n_clusters_per_class=1,n_classes=2,flip_y=0.1)
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=1)
dtrain=xgb.DMatrix(X_train,y_train)
dtest=xgb.DMatrix(X_test,y_test)
param={'max_depth':5,'eta':0.5,'verbosity':1,'objective':'binary:logistic'}
raw_model=xgb.train(param,dtrain,num_boost_round=20)
pred_train_raw=raw_model.predict(dtrain)
for i in range(len(pred_train_raw)):
    if pred_train_raw[i]>0.5:
        pred_train_raw[i]=1
    else:
        pred_train_raw[i]=0
print('train_accuracy:',accuracy_score(dtrain.get_label(),pred_train_raw))

pred_test_raw=raw_model.predict(dtest)
for i in range(len(pred_test_raw)):
    if pred_test_raw[i]>0.5:
        pred_test_raw[i]=1
    else:
        pred_test_raw[i]=0
print('test_accuracy:',accuracy_score(dtest.get_label(),pred_test_raw))

参数优化参考:https://www.cnblogs.com/pinard/p/11114748.html

参考文献:

XGBoost算法原理小结https://www.cnblogs.com/pinard/p/10979808.html

https://blog.csdn.net/qq_19446965/article/details/82079486

https://blog.csdn.net/qq_24519677/article/details/81809157

二、bagging算法

Bagging算法基于自助采样法随机得到一些样本训练集,用来学习不同的基学习分类器,然后对不同的基学习分类器得到的结果投票得出最终分类结果。随机森林也算bagging的一种,有一点区别在于随机森林在构建决策树时会随机选择样本特征中的一部分来进行划分。

随机森林:随机森林集成了多棵决策树,每棵决策树有一个分类结果,将投票次数最多的类别作为最终输出。随机森林可以处理大量的输入变数,可以产生高准确度的分类器。

随机森林算法步骤:

1)假设训练集的大小为N,对每棵树,有放回地随机抽取N个样本(包括可能重复的样本)

2)假设每个样本的特征为M,随机地从M中抽取m个特征,每次树进行分裂时,从这m个特征中选取最优的特征

3)对每棵决策树选定样本和特征后,使用CART进行计算,不剪枝

4)得到决策树后,对每棵树的输出进行投票,投票最多的类作为随机森林的决策。
 

import numpy as np
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
import pandas as pd
iris=load_iris()
df=pd.DataFrame(iris.data,columns=iris.feature_names)
df['is_train']=np.random.uniform(0,1,len(df))<=.75
df['target']=iris.target
df.head(10)
train,test=df[df['is_train']==True],df[df['is_train']==False]
features=df.columns[:4]
clf=RandomForestClassifier(n_jobs=2)
y=train['target']
clf.fit(train[features],y)
preds=iris.target_names[clf.predict(test[features])]
species=iris.target_names[test['target'].values]
pd.crosstab(species, preds, rownames=['actual'], colnames=['preds'])

参考:https://blog.csdn.net/qq_39521554/article/details/80714734

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值