机器学习实战_Python3.7_AdaBoost元算法

AdaBoost 元算法

 AdaBoost 元算法是基于某一个前面介绍过的算法(比如 kNN、决策树、SVM)的,以决策树为例,我们的目标不是直接训练完整的决策树,寻求最优的参数设置,而是用很多不完美的决策树,将它们的计算结果经过加权求和,作为预测的依据。简单的说就是“三个臭皮匠,赛过一个诸葛亮”。

算法从一个初始的权重向量 D 开始,训练得到决策树 A (可能是很简单的预测方式,并且预测准确率不高),根据 A 的预测情况计算决策树 A 的权重 alpha(A),并更新样本的权重向量 D(A):

根据 D(A) 训练下一个决策树 B ,再根据 B 的预测情况计算 alpha(B) 和 D(B);如此不断迭代和修正,最终就得到了完整模型。

AdaBoost 元算法很容易理解,算法过程用到的公式也比较简单,不过其背后的“分治”思想很值得深入体会和挖掘。


基于单层决策树的 AdaBoost 元算法

from numpy import *

# 构建简易数据集
def loadSimpData():
    datMat = matrix([[1., 2.1],[2., 1.1],[1.3, 1.],[1., 1.],[2., 1.]])
    classLabels = [1.0, 1.0, -1.0, -1.0, 1.0]
    return datMat,classLabels

# 辅助函数:通过阈值比较对数据进行分类
# dataMatrix:特征集
# dimen:要处理的特征在特征集中的下标
# threshVal:阈值
# threshIneq:正负标签划分方式
def stumpClassify(dataMatrix, dimen, threshVal, threshIneq):
    retArray = ones((shape(dataMatrix)[0], 1))
    if(threshIneq == 'lt'):
        retArray[dataMatrix[:, dimen] <= threshVal] = -1.0
    else:
        retArray[dataMatrix[:, dimen] > threshVal] = -1.0
    return retArray

# 单层决策树(决策树的一个简化版本)
# 遍历所有的特征、各特征下的多种取值、大于或小于两种方式
# 找到在该权重向量 D 下的最优的单层决策树
# dataArr:特征集
# classLabels:标签集
# D:权重向量
def buildStump(dataArr, classLabels, D):
    dataMatrix = mat(dataArr)
    labelMat = mat(classLabels).T
    m, n = shape(dataMatrix)
    # 设定步长划分数
    numSteps = 10.0
    # 记录决策树结构
    bestStump = {}
    # 记录最佳分类结果
    bestClasEst = mat(zeros((m, 1)))
    # 初始化最小错误率为无穷大
    minError = inf
    # 遍历所有特征
    for i in range(n):
        # 计算步长
        rangeMin = dataMatrix[:, i].min()
        rangeMax = dataMatrix[:, i].max()
        stepSize = (rangeMax - rangeMin) / numSteps
        # 遍历所有步长限定的所有可取阈值
        for j in range(-1, int(numSteps) + 1):
            # 遍历 > 和 < 两种判断方式
            for inequal in ['lt', 'gt']:
                # 计算分类结果
                threshVal = (rangeMin + float(j) * stepSize)
                predictedVals = stumpClassify(dataMatrix, i, threshVal, inequal)
                # 统计分类的错误情况
                errArr = mat(ones((m, 1)))
                errArr[predictedVals == labelMat] = 0
                # 计算加权错误率
                weightedError = D.T * errArr
                # 更新最优分类方法
                if weightedError < minError:
                    minError = weightedError
                    bestClasEst = predictedVals.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = threshVal
                    bestStump['ineq'] = inequal
    return bestStump, minError, bestClasEst

# 基于单层决策树 DS 的训练过程
# dataArr、classLabels:数据集
# numIt:迭代次数
def adaBoostTrainDS(dataArr, classLabels, numIt = 40):
    # 存储所有弱分类器的 DS 数组
    weakClassArr = []
    # 样本数
    m = shape(dataArr)[0]
    # 初始化权重向量 D
    D = mat(ones((m,1)) / m)
    # 记录每个数据点的类别估计的累计值
    aggClassEst = mat(zeros((m,1)))
    for i in range(numIt):
        # 根据当前的权重向量 D 生成一个 DS
        bestStump,error,classEst = buildStump(dataArr,classLabels,D)
        # 计算 alpha (当 error 为 0,用 1e-16 替代,避免除零溢出)
        alpha = float(0.5 * log((1.0 - error) / max(error, 1e-16)))
        # 将 alpha 存入这个 DS 的字典
        bestStump['alpha'] = alpha
        # 将该 DS 加入 DS 数组
        weakClassArr.append(bestStump)
        # 计算用于下一轮迭代的权重向量 D
        expon = multiply(-1 * alpha * mat(classLabels).T, classEst)
        D = multiply(D, exp(expon))
        D = D / D.sum()
        # 记录每个数据点的类别估计的累计值
        aggClassEst += alpha * classEst
        # 计算当前累计值下的分类错误情况
        aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1)))
        errorRate = aggErrors.sum() / m
        print("total error: ",errorRate)
        # 如果已经全部正确分类,则退出循环
        if(errorRate == 0.0):
            break
    return weakClassArr,aggClassEst

# AdaBoost分类函数
# datToClass:测试数据的特征集
# classifierArr:训练好的多个 DS 字典组成的列表
def adaClassify(datToClass, classifierArr):
    # 测试数据的特征集
    dataMatrix = mat(datToClass)
    # 测试样本数
    m = shape(dataMatrix)[0]
    # 记录每个数据点的类别估计的累计值
    aggClassEst = mat(zeros((m,1)))
    # 遍历每个 DS
    for i in range(len(classifierArr)):
        # 计算当前 DS 的分类结果
        classEst = stumpClassify(dataMatrix,classifierArr[i]['dim'],classifierArr[i]['thresh'],classifierArr[i]['ineq'])
        # 通过 alpha 加权
        aggClassEst += classifierArr[i]['alpha'] * classEst
        print(aggClassEst)
    return sign(aggClassEst)

dataArr, classLabels = loadSimpData()
weakClassArr, aggClassEst = adaBoostTrainDS(dataArr, classLabels)
classResult = adaClassify([[0,0],[5,5]], weakClassArr)
print(classResult)

运行结果:

[[-0.69314718]
 [ 0.69314718]]
[[-1.66610226]
 [ 1.66610226]]
[[-2.56198199]
 [ 2.56198199]]
[[-1.]
 [ 1.]]

Process finished with exit code 0

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值