前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >干货 | 集成学习综述与代码实现

干货 | 集成学习综述与代码实现

作者头像
zenRRan
发布2019-11-20 17:40:42
5580
发布2019-11-20 17:40:42
举报

阅读大概需要14分钟 跟随小博主,每天进步一丢丢

转载自 AI部落联盟 1. 集成学习

  • 定义

顾名思义,就是将多个单一模型进行组合,最后形成一个更好的模型的过程。之所以组合多个单一学习器,是因为很多时候单一学习器的效果不够理想,多个模型组合可以互帮互助,各取所长,从而能够更好的完成任务。集成学习一般的结构是先学习单一的学习器,之后通过某种策略将其组合在一起。

  • 条件

(a)首先应该保证分类器之间的差异性,如果分类器都相同,那么组合的出来的结果是不会有变化的。 (b)每个个体分类器的精度必须大于0.5,如果个体分类器的精度低于0.5,那集成之后的精度低于规模的增大而降低。但如果精度是大于0.5的,最后的分类结果会趋于1。

  • 分类

根据个体学习器的生成方式,目前的集成学习方法大致可以分成两类:第一类是单个学习器之间有着很强的依赖关系,需要以串行的序列化的方式生成,代表方法:Boosting。Boosting方法中也有很多分类:Adaboost、GBDT等等。第二类就是个体学习器之间不存在很强的依赖关系,学习器可以并行生成,代表方法:Bagging 和Random Forest。 2. Bagging和Boosting 2.1 Bagging Bagging又称为套袋法: 每次从样本集合中有放回地抽取n个值,一共抽取k轮,形成k个训练集合,训练集合之间彼此独立。对于分类问题,k个训练器可以训练出k个模型,从而产生k个结果,对于回归问题,取均值作为预测结果。 2.2 Boosting 每次从样本集合中有放回地抽取n个值,一共抽取k轮,形成k个训练集合,训练集合之间彼此独立。对于分类问题,k个训练器可以训练出k个模型,从而产生k个结果,对于回归问题,取均值作为预测结果。 梯度提升的Boosting方法则是使用代价函数对上一轮训练的损失函数f的偏导数来拟合残差。 2.3 Bagging和Boosting的区别

  • 训练数据集

Bagging是每次从样本集中有放回地抽取n个样本,抽取k次,形成k个样本集合,样本集合之间相互独立; Boosting则是训练集合保持不变,每次变化的是训练集中样例的权重。

  • 样例权重

Bagging使用的是均匀采样,每个样例权重相等; Boosting根据上一轮结果调整权重,错误率越大权重越大。

  • 预测函数

Bagging所有的预测函数权重相同; Boosting预测函数权重不同,预测误差小的权重越大。

  • 并行计算

Bagging各个预测函数可以并行生成; Boosting只能顺序生成,因为后一个预测要用到上一个结果。 2.4 样本权值和模型权值 Boosting会减小在上一轮正确样本的权重,增大错误样本的权重(因为正确样本残差小,错误样本残差大。组合模型的时候会将错误率高的模型赋予低的权重,将错误率低的模型赋予高的权重,有助于增加组合后模型准确率。

3. 组合模型方式

3.1 平均法

(a)简单平均

将所有的个体学习器的数值型输出求平均。

(b)加权平均

各个学习器有自身的权重,根据权重来进行加权平均,代表算法:Adaboost。

3.2 学习法

当训练数据很多时,更加强大的结合策略就是学习法,也就是通过另一个学习器来进行组合。典型代表是Stacking。把个体学习器称之为初级学习器,用于结合的学习器称为次级学习器或者元学习器。

Stacking先从初始训练集训练出初级学习器,然后生成一个新的数据集来训练次级学习器。新的数据集是以初级学习器的输出作为样例,初始样本的标记被当做样例标记。

4. AdaBoost算法

4.1 核心思想

  • 权值的更新取决于上一轮训练结果,增大误分类的样本的权值,减小正确分类的样本权值,在下一轮训练的时候误分类样本会得到更多的关注,正确分类的样本得到的关注变少。
  • 因为每次挑选的是误差最小的分类器,增大误分类的样本的权重相当于增大当前分类器的误差,错误率高的分类器对应小权重,错误率低的分类器对应大权重。

4.2 前向分步算法

简单来说就是从前向后,每次只学习一个基函数,最后通过基函数的线性组合,去逼近优化目标函数。

4.3 算法步骤

AdaBoost的Python实现(iris数据集)

代码语言:javascript
复制
import os
import numpy as np
import pandas as pd
from sklearn.cross_validation import train_test_split
from sklearn.datasets import load_irisdef load_data():
   iris = load_iris()#导入数据
   #转换为dataframe
   df = pd.DataFrame(iris.data,columns=iris.feature_names)
   df['label'] = iris.target#导入标签
   #把0和1类拿出来
   df.columns = ['sepal length','sepal width','petal length','petal width','label']#重命名列名
   data = np.array(df.iloc[:100,[0,1,-1]])#前100行为分类为0和1两类
   #把为0的变成-1
   for i in range(len(data)):
       if data[i,-1]==0:#把0类的转换为-1类
           data[i,-1] = -1
   return data[:,0:2],data[:,-1]X,y = load_data()#导入数据
train_x,test_x,train_x,train_y = train_test_split(X,y,test_size=0.2,random_state=2333)#划分训练集和测试集
#定义Adaboost类
class Adaboost(object):
   def __init__(self,n_estimators=1,learning_rate = 0):
   '''
   n_estimators 分类器个数
   learning_rate 步长
   '''
       self.n_estimate = n_estimators
       self.learning_rate = learning_rate   def init_data(self,X,y):
   '''
   X:属性
   y:标签
   '''
       self.M,self.N = X.shape#属性一共有M行N列
       self.X = X#训练属性
       self.y = y#标签数据
       self.w = [1.0/self.M]*self.M#初始化权重为1/M
       self.alpha = []
       self.clf_set = []#模型参数集合   def _alpha(self,error):#误差越大 alpha值越小
       return 0.5*np.log((1-error)/error)   def _Z(self, weights, a, clf):
   '''
   a:各个分类器的权重
   weights:权重
   clf:compare_array
   '''
       return sum([weights[i]*np.exp(-1*a*self.y[i]*clf[i]) for i in range(self.M)])   def _w(self, a, clf, Z):#相当于给权重w做了一层softmax 归一化
   '''
   a:各个分类器的权重
   weights:权重
   clf:compare_array
   误分类self.y[i]*clf[i]=1权重增大 正确分类self.y[i]*clf[i]=-1权重变小
   '''
       for i in range(self.M):
           self.w[i] = self.w[i]*np.exp(-1*a*self.y[i]*clf[i])/ Z   #具体算法
   def G(self,feature,label,weights):#每次更新的是w
       #求出属性列中的最大值和最小值
       f_min = min(feature)
       f_max = max(feature)
       #在属性列上迭代的次数
       n_step = (f_max-f_min+self.learning_rate)//self.learning_rate
       error = 10000.0#定义为无穷大
       best_v = 0.0#表示属性中最好分类点的值
       direct,compare_array = None,None
       #direct表示优化方向
       #compare_array表示该方向对应的c_o_positive or c_o_negative数组
       for i in range(1,int(n_step)):
           v = f_min+self.learning_rate*i#每次增加的步长为learning_rate
           if v not in feature:#如果v不存在属性列中
               c_o_positive = np.array([1 if feature[k] > v else -1 for k in range(len(feature))])#大于v的label置为1 小于v的置为-1
               #print([weights[k] for k in range(len(feature)) if c_o_positive[k]!=label[k]])
               error_positive = sum([weights[k] for k in range(len(feature)) if c_o_positive[k]!=label[k]])#记录不等于label的weight并求和
               c_o_negative = np.array([-1 if feature[k] > v else 1 for k in range(len(feature))])#同上 但反向
               error_negative = sum([weights[k] for k in range(len(feature)) if c_o_negative[k]!=label[k]])
               if error_positive < error_negative:#如果正向误差小于反向误差
                   weight_error = error_positive#记录误差
                   _compare_array = c_o_positive
                   direct = 'positive'
               else:
                   weight_error = error_negative
                   _compare_array = c_o_negative
                   direct = 'negative'
               if weight_error < error:
                   error = weight_error#记录误差
                   best_v = v#记录最佳分类值
                   compare_array = _compare_array#记录label
       return best_v,error,compare_array,direct   def _G(self,x,v,direct):
       if direct=='positive':
           return 1 if x > v else -1
       else:
           return -1 if x>x else -1   def fit(self,X,y):
       self.init_data(X,y)#初始化类内参数
       for i in range(self.n_estimate):#迭代次数
           best_clf_error,best_v,clf_result = 100000,None,None
           #单个属性
           for j in range(self.N):#在属性列上迭代
               feature = self.X[:,j]#
               v,error,compare,direct = self.G(feature,self.y,self.w)
               if error<best_clf_error:
                   best_clf_error = error
                   best_v = v
                   final_direct = direct
                   clf_result = compare
                   axis = j
               if best_clf_error == 0:
                   break
           a = self._alpha(best_clf_error)#计算alpha 0.5*np.log((1-error)/error)
           self.alpha.append(a)#记录alpha
           z = self._Z(self.w,a,clf_result)
           self.clf_set.append((axis,best_v,final_direct))#clf_set集合
           self._w(a,clf_result,z)#修改self.w   def predict(self,feature):#预测函数(比较简单)
       result = 0.0
       for i in range(len(self.clf_set)):
           axis,best_v,final_direct = self.clf_set[i]
           f = feature[axis]
           result += self.alpha[i] * self._G(f,best_v,final_direct)
       return 1 if result >0 else -1   def score(self,X_test,y_test):#打分函数(比较简单)
       count = 0
       for i in range(len(X_test)):
           feature = X_test[i]
           if self.predict(feature) == y_test[i]:
               count += 1
       return count/len(X_test)
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-12-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 深度学习自然语言处理 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 阅读大概需要14分钟 跟随小博主,每天进步一丢丢
  • 3. 组合模型方式
  • 4. AdaBoost算法
相关产品与服务
GPU 云服务器
GPU 云服务器(Cloud GPU Service,GPU)是提供 GPU 算力的弹性计算服务,具有超强的并行计算能力,作为 IaaS 层的尖兵利器,服务于深度学习训练、科学计算、图形图像处理、视频编解码等场景。腾讯云随时提供触手可得的算力,有效缓解您的计算压力,提升业务效率与竞争力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档