算法思想:传统机器学习算法 (例如:决策树,逻辑回归等) 的目标都是寻找一个最优分类器尽可能的将训练数据分开。集成学习 (Ensemble Learning) 算法的基本思想就是将多个分类器组合,从而实现一个预测效果更好的集成分类器。
1、集成学习分类之Bagging算法(并行)
1.1 Bootstrap sampling自助采样
模型的评估方法中有留一法(将数据集划分为两个互不相交的集合,一个做测试集,一个做训练集)和交叉验证方法(将数据分成k个大小相似互不相交的子集,每次使用k-1个子集做训练集,剩下的一个子集做测试集,以此循环进行k次的训练和测试,最后返回k次测试结果的均值。)。但是上述两种方法中都保留了一部分样本用于测试,所以实际模型所使用的训练集比源数据都要小,因此就会引入一些因训练样本规模不同而导致的估计偏差。另外一方面留一法受训练样本影响较小,但是计算复杂度又太高。因此为了解决减少训练样本规模不同造成的影响,同时还能比较高效地进行测试集的评估。自助法就是很好的解决方案。
booststrap抽样
在样本集D(样本数为m)内有放回的抽样,抽取数为m,每次抽取的概率相等为1/m,可能重复抽取。我们做一个简单的估计,样本m次采样中不被采样的概率为
?取极限得到原数据集D中36.8%的样本没有出现在采样数据集D1中。我们可以使用D1作为训练集,D-D1作为测试集。这样实际评估的模型与期望的模型都使用m个训练样本,而我们仍有数据总量的1/3的,没有在训练集中出现的样本用于测试。
1.2 Bagging算法?(并行)
?1.3 Bagging算法性能
(1)Bagging是一个很高效的集成学习算法
(2)Bagging与下面讲的AdaBoost只适用于二分类不同,它能不经修改地用于多分类、回归任务。
(3)自助bootstrap采样过程还给Bagging带来了另一个优点:由于每个基学习器只使用了初始训练集中约63.2%的样本,剩下的约36.8%样本可用作验证集来泛化性能进行“包外样本评估(即:不同于训练数据的样本)”。
(4)从偏差-方差分解角度看,Bagging主要关注降低方差,因此它在不剪枝决策树、神经网络等易受样本扰动的学习器上效果更为明显。
2、集成学习分类之随机森林算法
2.1 算法详解
随机森林就是建立很多决策树,组成一个决策树的“森林”,通过多棵树投票来进行决策。这种方法能够有效地提高对新样本的分类准确度。
随机森林在以决策树为基学习器构建Bagging集成(样本的随机选取)的基础上,进一步在决策树的训练过程中引入随机属性选择。具体来说,传统决策树在选择划分属性时是在当前节点的属性集合(假设有d个属性)中选择一个最优属性;而在RF随机森林中,对基决策树的每个节点,先从该节点的属性集合中随机选择一个包含K个属性的子集,然后在从这个子集中选择一个最优属性用于划分。K=d就是传统决策树,K=1则是随机选取一个属性用于划分,一般情况
2.2 思考
- 为什么要随机抽样训练集?
如果不进行随机抽样,每棵树的训练集都一样,那么最终训练出的树分类结果也是完全一样。
- 为什么要有放回地抽样?
如果不是有放回的抽样,那么每棵树的训练样本都是不同的,都是没有交集的,这样每棵树都是“有偏的”,都是绝对“片面的”(当然这样说可能不对),也就是说每棵树训练出来都是有很大的差异的;而随机森林最后分类取决于多棵树(弱分类器)的投票表决。
2.3 随机森林的特点
随机森林简单、容易实现、计算开销小,被誉为“代表集成学习计数水平的方法”。可以看出随机森林只是对Bagging做了很小的改动。Bagging的多样性只是体现在样本的随机性,随机森林的基学习器的多样性不仅来自于样本的随机性,还来自于属性的随机性。随机森林随着学习器数目的增加,随机森林通常会收敛到更低的泛化误差。
(1)分类结果更加准确
(2)可以处理高维度的属性,并且不用做特征选择
(3)即使有很大部分数据遗失,仍可以维持高准确度
(4)学习过程快速
(5)在训练完成后,能够给出哪些属性比较重要
(6)容易实现并行化计算
(7)在训练过程中,能够检测到属性之间的相互影响
2.4 随机森林API
http://scikit-learn.org/0.17/modules/generated/sklearn.ensemble.RandomForestClassifier.html#sklearn.ensemble.RandomForestClassifier
2.5 随机森林的Sklearn实例
#1.数据导入
#1.1导入数据
import pandas as pd
#1.2.利用pandas的read.csv模块从互联网中收集泰坦尼克号数据集
titanic=pd.read_csv("data/titanic.csv")
titanic.info() #查看信息
#2人工选择特征pclass,age,sex
X=titanic[['pclass','age','sex']]
y=titanic['survived']
#3.特征工程
#数据的填补
X['age'].fillna(X['age'].mean(),inplace=True)
#数据的切分
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test =train_test_split(X,y,test_size=0.25,random_state=22)
#将数据转化为特征向量
from sklearn.feature_extraction import DictVectorizer
vec=DictVectorizer(sparse=False)
X_train=vec.fit_transform(X_train.to_dict(orient='records'))
X_test=vec.transform(X_test.to_dict(orient='records'))
#4.使用单一的决策树进行模型的训练及预测分析
from sklearn.tree import DecisionTreeClassifier
dtc=DecisionTreeClassifier()
dtc.fit(X_train,y_train)
dtc_y_pred=dtc.predict(X_test)
dtc.score(X_test,y_test)
#5.随机森林进行模型的训练和预测分析
from sklearn.ensemble import RandomForestClassifier
rfc=RandomForestClassifier(max_depth=6,random_state=9)
rfc.fit(X_train,y_train)
rfc_y_pred=rfc.predict(X_test)
rfc.score(X_test,y_test)
#6.性能评估
from sklearn.metrics import classification_report
print("dtc_report:",classification_report(dtc_y_pred,y_test))
print("rfc_report:",classification_report(rfc_y_pred,y_test))
超参数选择代码:
# 随机森林去进行预测
# 1 实例化随机森林
rf = RandomForestClassifier()
# 2 定义超参数的选择列表
param={"n_estimators":[80,100,200], "max_depth": [2,4,6,8,10,12],"random_state":[9]}
# 超参数调优
# 3 使用GridSearchCV进行网格搜索
from sklearn.model_selection import GridSearchCV
gc = GridSearchCV(rf, param_grid=param, cv=2)
gc.fit(X_train, y_train)
print("随机森林预测的准确率为:", gc.score(X_test, y_test))
3、Boosting框架(串行)
3.1 算法机制
Boosting是一组可将弱学习器升为强学习器算法。这类算法的工作机制类似:
1.先从初始训练集训练出一个基学习器
2.在根据基学习器的表现对训练样本分布进行调整,使得先前基学习器做错的训练样本在后续得到最大的关注。
3.然后基于调整后的样本分布来训练下一个基学习器;
4.如此重复进行,直至基学习器数目达到实现指定的值T为止。
5.再将这T个基学习器进行加权结合得到集成学习器。
简而言之:每新加入一个弱学习器,整体能力就会得到提升
Boosting算法的著名代表就是Adaboost算法。
因此,对于Boosting算法,存在两个问题:
- 在每一轮中如何调整训练集,使训练的弱分类器得以进行;(调整样本权值)
- 如何将各个弱分类器联合起来形成强分类器。 (调整模型权值)
3.2 提升的概念强化
提升Boosting是一个机器学习技术,可以用于回归和分类问题,它每一步产生一个弱预测模型(如决策树)并加权累加到总模型中;如果每一步的弱预测模型生成都是依据损失函数的梯度方向,则称之为梯度提升(GradientBoosting)。
梯度提升算法首先给定一个目标损失函数,它的定义域是所有可行的弱函数集合(基函数);提升算法通过迭代的选择一个负梯度方向上的基函数来逐渐逼近局部极小值。这种在函数域的梯度提升观点对机器学习有很大影响。
提升的理论意义:如果一个问题存在弱分类器,则可以通过提升的办法得到强分类器。
3、集成学习分类之Adaboost算法?
3.1 简介
AdaBoost自适应提升学习算法和Boosting考虑的点一样
Adaboost自适应在于:“关注”被错分的样本,“器重”性能好的弱分类器:(观察下图)
(1)不同的训练集--->调整样本权重
(2)“关注”--->增加错分样本权重
(3)“器重”--->好的分类器权重大
(4) 样本权重间接影响分类器权重
AdaBoost算法的两个核心步骤:
权值调整:AdaBoost算法提高那些被前一轮基分类器错误分类样本的权值,而降低那些被正确分类样本的权值。从而使得那些没有得到正确分类的样本,由于权值的加大而受到后一轮基分类器的更大关注。
基分类器组合:AdaBoost采用加权多数表决的方法。
- 加大分类误差率较小的弱分类器的权值,使得它在表决中起到较大的作用。
- 减小分类误差率较大的弱分类器的权值,使得它在表决中起较小的作用。
3.2 AdaBoost特点
AdaBoost把多个不同的弱分类算法,用一种非随机的方式组合起来,表现出惊人的性能。
1,可以使用各种方法构建子分类器,Adaboost算法提供的是框架;
2,子分类器容易构造;
3,速度快,且基本不用调参数;
4,泛化错误率低。
3.3 AdaBoost步骤
Adaboost迭代算法有3步:
1.初始化训练数据的权值分布:假设有N个样本,每个样本赋予相同权值1/N。
2.训练弱分类器:本轮训练中,若某样本分错,则提高它的权值,相反分类正确的样本被降低权值。然后,权值更新过的全体样本被用于训练下一个分类器,使得下一个分类器更关注权重大的难分样本。多次迭代,训练多个弱分类器。
3.加权组合弱分类器:加大分类误差率小的弱分类器的权重,使其在最终表决中起较大作用,而降低分类误差率大的弱分类器的权重,使其在最终表决中起较小作用。
3.4 AdaBoost实例葡萄酒数据
# 获取数据
import pandas as pd
df_wine = pd.read_csv('data/wine.data')
# 修改列名
df_wine.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash', 'Alcalinity of ash', 'Magnesium', 'Total phenols',
'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins', 'Color intensity', 'Hue', 'OD280/OD315 of diluted wines',
'Proline']
# 去掉一类(1,2,3)
df_wine = df_wine[df_wine['Class label'] != 1]
# 获取特征值和目标值
X = df_wine[['Alcohol', 'Hue']].values
y = df_wine['Class label'].values
# 切分数据
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
# 类别转化 (2,3)=>(0,1)
le = LabelEncoder()
y = le.fit_transform(y)
# 划分训练集和测试集
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.4,random_state=1)
# 在500棵单层决策树上训练AdaBoost
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
# 机器学习(决策树和AdaBoost)
tree = DecisionTreeClassifier(criterion='entropy',max_depth=1,random_state=0)
ada= AdaBoostClassifier(base_estimator=tree,n_estimators=500,learning_rate=0.1,random_state=0)
from sklearn.metrics import accuracy_score
# 决策树和AdaBoost分类器性能评估
# 决策树性能评估
tree = tree.fit(X_train,y_train)
y_train_pred = tree.predict(X_train)
y_test_pred = tree.predict(X_test)
tree_train = accuracy_score(y_train,y_train_pred)
tree_test = accuracy_score(y_test,y_test_pred)
print('Decision tree train/test accuracies %.3f/%.3f' % (tree_train,tree_test))
# Decision tree train/test accuracies 0.845/0.854
# AdaBoost性能评估
ada = ada.fit(X_train,y_train)
y_train_pred = ada.predict(X_train)
y_test_pred = ada.predict(X_test)
ada_train = accuracy_score(y_train,y_train_pred)
ada_test = accuracy_score(y_test,y_test_pred)
print('Adaboost train/test accuracies %.3f/%.3f' % (ada_train,ada_test))
# Adaboost train/test accuracies 1/0.875
# 绘制决策区域形状
import numpy as np
import matplotlib.pyplot as plt
x_min,x_max = X_train[:,0].min() - 1,X_train[:,0].max() + 1
y_min,y_max = X_train[:,1].min() - 1,X_train[:,1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min,x_max,0.1),np.arange(y_min,y_max,0.1))
f,axarr = plt.subplots(1,2,sharex='col',sharey='row',figsize=(8,3))
for idx,clf,tt in zip([0,1],[tree,ada],['Decision Tree', 'AdaBoost']):
clf.fit(X_train,y_train)
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
axarr[idx].contourf(xx,yy,Z,alpha = 0.3)
axarr[idx].scatter(X_train[y_train==0,0],X_train[y_train==0,1],c='blue',marker='^')
axarr[idx].scatter(X_train[y_train==1,0],X_train[y_train==1,1],c='red',marker='o')
axarr[idx].set_title(tt)
axarr[0].set_ylabel('Alcohol', fontsize=12)
plt.text(10.2,-1.2,s='Hue',ha='center',va='center',fontsize = 12)
plt.tight_layout()
4、GBDT梯度提升决策树算法
4.1 简介
首先,GBDT使用的决策树是CART回归树,无论是处理回归问题还是二分类以及多分类,GBDT使用的决策树通通都是都是CART回归树。
为什么不用CART分类树呢?
答案:因为GBDT每次迭代要拟合的是梯度值,是连续值所以要用回归树。
分类树和回归树区别?
答案:(1)对于回归树算法来说最重要的是寻找最佳的划分点,那么回归树中的可划分点包含了所有特征的所有可取的值。
(2)在分类树中最佳划分点的判别标准是熵或者基尼系数,都是用纯度来衡量的,但是在回归树中的样本标签是连续数值,所以再使用熵之类的指标不再合适,取而代之的是平方误差,它能很好的评判拟合程度。
4.2 原理简述
基本原理:
① 训练一个模型m1,产生错误e1
② 针对e1训练一个模型m2,产生错误e2
③ 针对e2训练第三个模型m3,产生错误e3 .....
④ 最终预测结果是:m1+m2+m3+.....
GBDT是boosting的一种方法,主要思想:
每一次建立单个分类器时,是在之前建立的模型的损失函数的梯度下降方向。
损失函数越大,说明模型越容易出错,如果我们的模型能让损失函数持续的下降,则说明我们的模型在持续不断的改进,而最好的方式就是让损失函数在其梯度的方向上下降。
GBDT的核心在于每一棵树学的是之前所有树结论和的残差
残差就是真实值与预测值的差值
为了得到残差,GBDT中的树全部是回归树,不用分类树
Shrinkage(缩减)是 GBDT 的一个重要演进分支
Shrinkage的思想在于每次走一小步来逼近真实的结果,比直接迈大步的方式好
Shrinkage可以有效减少过拟合的风险。它认为每棵树只学到了一小部分,累加的时候只累加这一小部分,通过多学习几棵树来弥补不足。这累加的一小部分(步长*残差)来逐步逼近目标,所以各个树的残差是渐变的而不是陡变的。
GBDT可以用于回归问题(线性和非线性),也可用于分类问题
4.3 泰坦尼克号案例
#1.数据导入
#1.1导入数据
import pandas as pd
#1.2.利用pandas的read.csv模块从互联网中收集泰坦尼克号数据集
titanic=pd.read_csv("data/titanic.csv")
titanic.info() #查看信息
#2人工选择特征pclass,age,sex
X=titanic[['pclass','age','sex']]
y=titanic['survived']
#3.特征工程
#数据的填补
X['age'].fillna(X['age'].mean(),inplace=True)
#数据的切分
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test =train_test_split(X,y,test_size=0.25,random_state=22)
#将数据转化为特征向量
from sklearn.feature_extraction import DictVectorizer
vec=DictVectorizer(sparse=False)
X_train=vec.fit_transform(X_train.to_dict(orient='records'))
X_test=vec.transform(X_test.to_dict(orient='records'))
# 三种分类器训练及预测
#1.使用单一的决策树进行模型的训练及预测分析
from sklearn.tree import DecisionTreeClassifier
dtc=DecisionTreeClassifier()
dtc.fit(X_train,y_train)
dtc_y_pred=dtc.predict(X_test)
print("score",dtc.score(X_test,y_test))
#2.随机森林进行模型的训练和预测分析
from sklearn.ensemble import RandomForestClassifier
rfc=RandomForestClassifier(random_state=9)
rfc.fit(X_train,y_train)
rfc_y_pred=rfc.predict(X_test)
print("score:forest",rfc.score(X_test,y_test))
#3.GBDT进行模型的训练和预测分析
from sklearn.ensemble import GradientBoostingClassifier
gbc=GradientBoostingClassifier()
gbc.fit(X_train,y_train)
gbc_y_pred=gbc.predict(X_test)
print("score:GradientBoosting",gbc.score(X_test,y_test))
#三种分类器训练及预测
from sklearn.metrics import classification_report
print("dtc_report:",classification_report(dtc_y_pred,y_test))
print("rfc_report:",classification_report(rfc_y_pred,y_test))
print("gbc_report:",classification_report(gbc_y_pred,y_test))
|