关于机器学习:机器学习算法-AdaBoost-详解

43次阅读

共计 5397 个字符,预计需要花费 14 分钟才能阅读完成。

1. 集成学习概述

1.1. 定义

集成学习(Ensemble learning)就是将若干个弱分类器通过肯定的策略组合之后产生一个强分类器。
弱分类器(Weak Classifier)指的就是那些分类准确率只比随机猜想略好一点的分类器,而强分类器(
Strong Classifier)的分类准确率会高很多。这里的 ” 强 ”&” 弱 ” 是绝对的。某些书中也会把弱分类器称
为“基分类器”。

目前集成学习算法的流派次要有两种:

  • bagging
  • boosting

1.2. bagging

装袋(bagging)又称自主汇集(bootstrap aggregating),是一种依据平均概率分布从数据集中反复
抽样(有放回的)的技术。每个新数据集和原始数据集的大小相等。因为新数据集中的每个样本都是从
原始数据集中有放回的随机抽样进去的,所以新数据集中可能有反复的值,而原始数据集中的某些样本
可能基本就没呈现在新数据集中。

bagging 办法的流程,如下图所示:

  • 有放回的随机抽样:

自主采样法(Bootstap sampling),也就是说对于 m 个样本的原始数据集,每次
随机选取一个样本放入采样集,而后把这个样本从新放回原数据集中,而后再进行下一个样本的随机抽
样,直到一个采样集中的数量达到 m,这样一个采样集就构建好了,而后咱们能够反复这个过程,生成
n 个这样的采样集。也就是说,最初造成的采样集,每个采样集中的样本可能是反复的,也可能原数据
集中的某些样本基本就没抽到,并且每个采样集中的样本分布可能都不一样。

依据有放回的随机抽样结构的 n 个采样集,咱们就能够对它们别离进行训练,失去 n 个弱分类器,而后根
据每个弱分类器返回的后果,咱们能够采纳肯定的组合策略失去咱们最初须要的强分类器。

bagging 办法的代表算法是 随机森林 ,精确的来说,随机森林是 bagging 的一个特化进阶版,所谓的特
化是因为 随机森林的弱学习器都是决策树 。所谓的进阶是随机森林在 bagging 的样本随机采样根底上,
又加上了 特色的随机抉择,其根本思维没有脱离 bagging 的领域。

1.3. boosting

boosting 是一个迭代的过程,用来自适应地扭转训练样本的散布,使得弱分类器聚焦到那些很难分类的
样本上。它的做法是给每一个训练样本赋予一个权重,在每一轮训练完结时主动地调整权重。

boosting 办法的流程,如下图所示:

boosting 办法的代表算法有 Adaboost、GBDT、XGBoost 算法

1.4. 联合策略

1.4.1. 平均法

对于数值类的回归预测问题,通常应用的联合策略是平均法,也就是说,对于若干个弱学习器的输入进
行均匀失去最终的预测输入。

假如咱们最终失去的 n 个弱分类器为

最简略的均匀是算术平均,也就是说最终预测是

如果每个弱分类器有一个权重 w,则最终预测是

1.4.2. 投票法

对于分类问题的预测,咱们通常应用的是投票法。假如咱们的预测类别是

对于任意一个预测样本 x,咱们的 n 个弱学习器的预测后果别离是

最简略的投票法是绝对少数投票法,也就是咱们常说的多数遵从少数,也就是 n 个弱学习器的对样本 x 的
预测后果中,数量最多的类别 为最终的分类类别。如果不止一个类别取得最高票,则随机抉择一个做
最终类别。

略微简单的投票法是绝对多数投票法,也就是咱们常说的要票过半数。在绝对少数投票法的根底上,不
光要求取得最高票,还要求票过半数。否则会回绝预测。

更加简单的是加权投票法,和加权平均法一样,每个弱学习器的分类票数要乘以一个权重,最终将各个
类别的加权票数求和,最大的值对应的类别为最终类别。

1.4.3. 学习法

前两种办法都是对弱学习器的后果做均匀或者投票,绝对比较简单,然而可能学习误差较大,于是就有
了学习法这种办法,对于学习法,代表办法是 stacking,当应用 stacking 的联合策略时,咱们不是对弱
学习器的后果做简略的逻辑解决,而是再加上一层学习器,也就是说,咱们将训练集弱学习器的学习结
果作为输出,将训练集的输入作为输入,从新训练一个学习器来失去最终后果。

在这种状况下,咱们将弱学习器称为高级学习器,将用于联合的学习器称为次级学习器。对于测试集,
咱们首先用高级学习器预测一次,失去次级学习器的输出样本,再用次级学习器预测一次,失去最终的
预测后果。

2. AdaBoost

Adaboost 是 adaptive boosting(自适应 boosting)的缩写。算法步骤如下:

2.1. 计算样本权重

赋予训练集中每个样本一个权重,形成权重向量 D,将权重向量 D 初始化相等值。设定咱们有 m 个样本,每个样本的权重都相等,则权重为

2.2. 计算错误率

在训练集上训练出一个弱分类器,并计算分类器的错误率:

2.3. 计算弱分离器权重

为以后分类器赋予权重值 alpha,则 alpha 计算公式为:

2.4. 调整权重值

依据上一次训练后果,调整权重值(上一次分对的权重升高,分错的权重减少

如果第 i 个样本被正确分类,则该样本权重更改为:

如果第 i 个样本被分错,则该样本权重更改为:

把下面两个公式汇整成一个:

之后,在同一数据集上再一次训练弱分类器,而后循环上述过程,直到训练错误率为 0,或者弱分类器
的数目达到指定值。

2.5. 后果

循环完结后,咱们能够失去咱们的强分类器的预测后果:

3. 基于单层决策树构建弱分类器

单层决策树(decision stump)也称决策树桩,是一种简略的决策树。咱们曾经讲过决策树的相
关原理了,接下来咱们一起来构建一个单层决策树,它仅仅基于单个特色来做决策。因为这棵树只有一
次决裂过程,因而它实际上就是一个树桩。

3.1. 构建数据集

  • 咱们先构建一个简略数据集来确保咱们写出的函数可能失常运行。
import pandas as pd
import numpy as np

# 取得特色矩阵和标签矩阵
def get_Mat(path):
    dataSet = pd.read_table(path,header = None)
    xMat = np.mat(dataSet.iloc[:,:-1].values)
    yMat = np.mat(dataSet.iloc[:,-1].values).T
    return xMat,yMat

xMat,yMat = get_Mat('simpdata.txt')
  • 构建数据可视化函数,并运行查看数据分布
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['simhei']
%matplotlib inline

# 数据集可视化函数
def showPlot(xMat,yMat):
    x=np.array(xMat[:,0])
    y=np.array(xMat[:,1])
    label = np.array(yMat)
    plt.scatter(x,y,c=label)
    plt.title('单层决策树测试数据')
    plt.show()
    
showPlot(xMat,yMat)

3.2. 构建单层决策树

咱们会建设两个函数来实现咱们的单层决策树:

第一个函数用来测试是否有某个值小于或者大于咱们正在测试的阈值。

"""
函数性能:单层决策树分类函数
参数阐明:
    xMat: 特色矩阵
    i: 第 i 列,也就是第几个特色
    Q: 阈值
    S: 标记
返回:
    re: 分类后果
"""

def Classify0(xMat,i,Q,S):
    re = np.ones((xMat.shape[0],1)) # 初始化 re 为 1
    if S == 'lt':
        re[xMat[:,i] <= Q] = -1 # 如果小于阈值, 则赋值为 -1
    else:
        re[xMat[:,i] > Q] = -1 # 如果大于阈值, 则赋值为 -1
    return re

第二个函数略微简单一些,会在一个加权数据集中循环,并找到具备最低错误率的单层决策树

"""
函数性能:找到数据集上最佳的单层决策树
参数阐明:
    xMat:特色矩阵
    yMat:标签矩阵
    D:样本权重
返回:
    bestStump:最佳单层决策树信息
    minE:最小误差
    bestClas:最佳的分类后果
"""

def get_Stump(xMat,yMat,D):
    m,n = xMat.shape # m 为样本个数,n 为特色数
    Steps = 10 # 初始化一个步数
    bestStump = {} # 用字典模式来贮存树桩信息
    bestClas = np.mat(np.zeros((m,1))) # 初始化分类后果为 1
    minE = np.inf # 最小误差初始化为正无穷大
    for i in range(n): # 遍历所有特色
        Min = xMat[:,i].min() # 找到特色中最小值
        Max = xMat[:,i].max() # 找到特色中最大值
        stepSize = (Max - Min) / Steps # 计算步长
        for j in range(-1, int(Steps)+1):
            for S in ['lt', 'gt']: # 大于和小于的状况,均遍历。lt:less than,gt:greater than
                Q = (Min + j * stepSize) # 计算阈值
                re = Classify0(xMat, i, Q, S) # 计算分类后果
                err = np.mat(np.ones((m,1))) # 初始化误差矩阵
                err[re == yMat] = 0 # 分类正确的, 赋值为 0
                eca = D.T * err # 计算误差
                # print(f'切分特色: {i}, 阈值:{np.round(Q,2)}, 标记:{S}, 权重误差:{np.round(eca,3)}')
                if eca < minE: # 找到误差最小的分类形式
                minE = eca
                bestClas = re.copy()
                bestStump['特色列'] = i
                bestStump['阈值'] = Q
                bestStump['标记'] = S
    return bestStump,minE,bestClas

测试函数并运行查看后果:

m = xMat.shape[0]
D = np.mat(np.ones((m, 1)) / m) # 初始化样本权重(每个样本权重相等)bestStump,minE,bestClas= get_Stump(xMat,yMat,D)

4. AdaBoost 代码

用 python 代码来实现完整版 AdaBoost 算法

"""
函数性能:基于单层决策树的 AdaBoost 训练过程
参数阐明:xMat:特色矩阵
    yMat:标签矩阵
    maxC:最大迭代次数
返回:weakClass:弱分类器信息
    aggClass:类别估计值(其实就是更改了标签的估计值)"""

def Ada_train(xMat, yMat, maxC = 40):
    weakClass = []
    m = xMat.shape[0]
    D = np.mat(np.ones((m, 1)) / m) # 初始化权重
    aggClass = np.mat(np.zeros((m,1)))
    for i in range(maxC):
        Stump, error, bestClas = get_Stump(xMat, yMat,D) # 构建单层决策树
        
        # print(f"D:{D.T}")
        alpha=float(0.5 * np.log((1 - error) / max(error, 1e-16))) # 计算弱分类器权重 alpha
        Stump['alpha'] = np.round(alpha,2) # 存储弱学习算法权重, 保留两位小数
        weakClass.append(Stump) # 存储单层决策树
        
        # print("bestClas:", bestClas.T)
        expon = np.multiply(-1 * alpha *yMat, bestClas) # 计算 e 的指数项
        D = np.multiply(D, np.exp(expon))
        D = D / D.sum() # 依据样本权重公式,更新样本权重
        aggClass += alpha * bestClas #更新累计类别估计值
        
        # print(f"aggClass: {aggClass.T}" )
        aggErr = np.multiply(np.sign(aggClass) != yMat, np.ones((m,1)))# 计算误差
        errRate = aggErr.sum() / m
        
        # print(f"分类错误率: {errRate}")
        if errRate == 0: break # 误差为 0,退出循环
    return weakClass, aggClass
  • 运行函数,查看后果:
weakClass, aggClass =Ada_train(xMat, yMat, maxC = 40)
weakClass
aggClass

5. 基于 AdaBoost 的分类

这里咱们应用弱分类器的加权求和来计算最初的后果。

"""
函数性能:AdaBoost 分类函数
参数阐明:data: 待分类样例
    classifys: 训练好的分类器
返回:
    分类后果
"""

def AdaClassify(data,weakClass):
    dataMat = np.mat(data)
    m = dataMat.shape[0]
    aggClass = np.mat(np.zeros((m,1)))
    for i in range(len(weakClass)): # 遍历所有分类器,进行分类
        classEst = Classify0(dataMat,
        weakClass[i]['特色列'],
        weakClass[i]['阈值'],
        weakClass[i]['标记'])
        aggClass += weakClass[i]['alpha'] * classEst
        
        # print(aggClass)
    return np.sign(aggClass)
  • 后果
AdaClassify([0,0],weakClass)

本文由 mdnice 多平台公布

正文完
 0