zoukankan      html  css  js  c++  java
  • 机器学习实战---集成学习AdaBoost算法

    一:案例学习

    (一)西瓜书

    (二)https://zhuanlan.zhihu.com/p/27126737(看这个即可了解AdaBoost算法原理)

    二:代码实现

    (一)数据加载

    import numpy as np
    import matplotlib.pyplot as plt
    
    def loadSimpData(): #获取数据
        data_X = np.array([
            [1,2.1],
            # [2,1.1],    #1.5 1.6
            [1.5,1.6],
            [1.3,1],
            [1,1],
            [2,1]
        ])
        data_Y = np.array([1,1,-1,-1,1])
    
        return data_X,data_Y
    plt.figure()
    cls_data_1 = data_X[np.where(data_Y==1)]
    cls_data_2 = data_X[np.where(data_Y==-1)]
    plt.scatter(cls_data_1[:,0],cls_data_1[:,1],s=30,c="b")
    plt.scatter(cls_data_2[:,0],cls_data_2[:,1],s=30,c="y",marker='s')
    plt.show()
    View Code

    (二)单层决策树生成函数

    #一:单层决策树生成函数
    #1.根据输入的特征列、阈值、不等号,获取当前的数据的类别为-11
    def stumpClassfiy(data_X,dimen,threshVal,threshIneq):   #传入数据集,特征选取维度,阈值,大于小于
        classArr = np.ones((data_X.shape[0],1))
        if threshIneq == "lt":
            classArr[np.where(data_X[:,dimen]<=threshVal)] = -1    #因为这里是小于等于,所以我们阈值到最大值,即可划分所有的数据集。见下方2
        else:
            classArr[np.where(data_X[:,dimen]>threshVal)] = -1
    
        return classArr
    
    #2.基于数据的权重向量D,来找来找数据集上的最佳的单层决策树
    def buildStump(data_X,data_Y,D):
        m,n = data_X.shape
        numSteps = 10   #设置步数,用来进行阈值选取
        bestStump = {}  #使用字典来保存多个返回值,包括阈值选取,特征列选取,不等号选取
        bestClasEst = np.zeros((m,1))   #用来保存最优的类别划分
        minError = np.inf   #保存最小误差(判断错误点的权重和)
    
        for i in range(n):  #循环所有的特征列
            rangeMin = np.min(data_X[:,i])
            rangeMax = np.max(data_X[:,i])  #获取当前列的最大、最小值,根据上面设置的步数,在下面获取步长
            stepSize = (rangeMax - rangeMin) / numSteps
            for j in range(-1,numSteps+1):  #循环步数,来获取阈值(从最小值-一个步长,到最大值)
                #获取阈值threshVal
                threshVal = rangeMin + j*stepSize
                for ineq in ['lt','gt']:    #因为在不同位置,我们选取大于或者等于得到的误差和是不同的,所以我们需要进行遍历,从而找出最优值
                    #获取预测的类别
                    predictClass = stumpClassfiy(data_X,i,threshVal,ineq)
                    #判断预测的类别和实际的类别是否相等,从而获取错误信息
                    errArr = np.ones((m,1))
                    # print(predictClass.shape,data_Y.shape)
                    errArr[predictClass==data_Y] = 0    #相等则为0,不计算误差
                    #获取加权后的误差
                    weightError = D.T@errArr    #注意转置,因为我们在adaboost训练函数传入的是列向量
                    if weightError < minError:
                        minError = weightError
                        bestClasEst = predictClass
                        bestStump['dimen'] = i
                        bestStump['thresh'] = threshVal
                        bestStump['ineq'] = ineq
    
        return bestStump,minError,bestClasEst   #因为后面更新α时,需要使用到误差的权重。更新权重的时候要使用到

    (三)基于单层决策树实现的AdaBoost训练过程

    #二:基于单层决策树实现的AdaBoost训练过程
    def adaBoostTrains(data_X,data_Y,numIt=40): #后面表示迭代次数,当然如果在迭代次数内,实现误差为0,则退出
        weakClassArr = []   #用来保存返回的数据
        m,n = data_X.shape
        D = np.array(np.ones((m,1))/m)  #初始化权重向量
        aggClassEst = np.zeros((m,1))   #错误率计算
        for i in range(numIt):  #进行迭代
            bestStump, minError, bestClasEst =buildStump(data_X,data_Y,D)
            print("D:",D)
            print("classEst",bestClasEst)
            alpha = 1/2*np.log((1-minError)/max(minError,1e-16))   #确保没有出错时,保证没有除0溢出
            print("alpha:",alpha)
            bestStump['alpha'] = alpha  #因为后面还需要alpha,所以这里保存
            weakClassArr.append(bestStump)  #将本次最情况的分类保存
            #重新计算权重
            expon = np.multiply(-1*alpha*data_Y,bestClasEst)    #看公式
            D = np.multiply(D,np.exp(expon))
    
            D = D / np.sum(D)   #进行归一化
    
            aggClassEst += alpha*bestClasEst    #错误率累加计算
            print("aggClassEst:",aggClassEst)
            arrErrors = np.multiply(np.sign(aggClassEst)!=data_Y,np.ones((m,1)))    #计算错误数目
            errorRate = arrErrors.sum() / m   #计算错误率
            print("error rate:",errorRate)
            if errorRate == 0:
                break
    
        return weakClassArr

    (四)实现预测函数

    #三:实现预测功能
    def adaClassify(data_sim,classfierArr): #传入测试数据和分类器
        #将所有的分类器的权重和即可得到最后结果
        m,n = data_sim.shape
        aggClassEst = np.zeros((m,1))
        for i in range(len(classfierArr)):
            classEst = stumpClassfiy(data_sim,classfierArr[i]['dimen'],classfierArr[i]['thresh'],classfierArr[i]['ineq'])
            aggClassEst += classEst*classfierArr[i]['alpha']    #累加权重
            print(aggClassEst)
        return np.sign(aggClassEst)

    (五)结果测试

    data_X,data_Y = loadSimpData()
    # print(adaBoostTrains(data_X,np.array([data_Y]).T))
    classfierArr = adaBoostTrains(data_X,np.array([data_Y]).T)
    print(adaClassify(np.array([[0,0]]),classfierArr))
    print(adaClassify(np.array([[5,5],[0,0]]),classfierArr))

    (六)全部代码

    import numpy as np
    import matplotlib.pyplot as plt
    
    def loadSimpData(): #获取数据
        data_X = np.array([
            [1,2.1],
            # [2,1.1],    #1.5 1.6
            [1.5,1.6],
            [1.3,1],
            [1,1],
            [2,1]
        ])
        data_Y = np.array([1,1,-1,-1,1])
    
        return data_X,data_Y
    
    #一:单层决策树生成函数
    #1.根据输入的特征列、阈值、不等号,获取当前的数据的类别为-11
    def stumpClassfiy(data_X,dimen,threshVal,threshIneq):   #传入数据集,特征选取维度,阈值,大于小于
        classArr = np.ones((data_X.shape[0],1))
        if threshIneq == "lt":
            classArr[np.where(data_X[:,dimen]<=threshVal)] = -1    #因为这里是小于等于,所以我们阈值到最大值,即可划分所有的数据集。见下方2
        else:
            classArr[np.where(data_X[:,dimen]>threshVal)] = -1
    
        return classArr
    
    #2.基于数据的权重向量D,来找来找数据集上的最佳的单层决策树
    def buildStump(data_X,data_Y,D):
        m,n = data_X.shape
        numSteps = 10   #设置步数,用来进行阈值选取
        bestStump = {}  #使用字典来保存多个返回值,包括阈值选取,特征列选取,不等号选取
        bestClasEst = np.zeros((m,1))   #用来保存最优的类别划分
        minError = np.inf   #保存最小误差(判断错误点的权重和)
    
        for i in range(n):  #循环所有的特征列
            rangeMin = np.min(data_X[:,i])
            rangeMax = np.max(data_X[:,i])  #获取当前列的最大、最小值,根据上面设置的步数,在下面获取步长
            stepSize = (rangeMax - rangeMin) / numSteps
            for j in range(-1,numSteps+1):  #循环步数,来获取阈值(从最小值-一个步长,到最大值)
                #获取阈值threshVal
                threshVal = rangeMin + j*stepSize
                for ineq in ['lt','gt']:    #因为在不同位置,我们选取大于或者等于得到的误差和是不同的,所以我们需要进行遍历,从而找出最优值
                    #获取预测的类别
                    predictClass = stumpClassfiy(data_X,i,threshVal,ineq)
                    #判断预测的类别和实际的类别是否相等,从而获取错误信息
                    errArr = np.ones((m,1))
                    # print(predictClass.shape,data_Y.shape)
                    errArr[predictClass==data_Y] = 0    #相等则为0,不计算误差
                    #获取加权后的误差
                    weightError = D.T@errArr    #注意转置,因为我们在adaboost训练函数传入的是列向量
                    if weightError < minError:
                        minError = weightError
                        bestClasEst = predictClass
                        bestStump['dimen'] = i
                        bestStump['thresh'] = threshVal
                        bestStump['ineq'] = ineq
    
        return bestStump,minError,bestClasEst   #因为后面更新α时,需要使用到误差的权重。更新权重的时候要使用到
    
    
    #二:基于单层决策树实现的AdaBoost训练过程
    def adaBoostTrains(data_X,data_Y,numIt=40): #后面表示迭代次数,当然如果在迭代次数内,实现误差为0,则退出
        weakClassArr = []   #用来保存返回的数据
        m,n = data_X.shape
        D = np.array(np.ones((m,1))/m)  #初始化权重向量
        aggClassEst = np.zeros((m,1))   #错误率计算
        for i in range(numIt):  #进行迭代
            bestStump, minError, bestClasEst =buildStump(data_X,data_Y,D)
            print("D:",D)
            print("classEst",bestClasEst)
            alpha = 1/2*np.log((1-minError)/max(minError,1e-16))   #确保没有出错时,保证没有除0溢出
            print("alpha:",alpha)
            bestStump['alpha'] = alpha  #因为后面还需要alpha,所以这里保存
            weakClassArr.append(bestStump)  #将本次最情况的分类保存
            #重新计算权重
            expon = np.multiply(-1*alpha*data_Y,bestClasEst)    #看公式
            D = np.multiply(D,np.exp(expon))
    
            D = D / np.sum(D)   #进行归一化
    
            aggClassEst += alpha*bestClasEst    #错误率累加计算
            print("aggClassEst:",aggClassEst)
            arrErrors = np.multiply(np.sign(aggClassEst)!=data_Y,np.ones((m,1)))    #计算错误数目
            errorRate = arrErrors.sum() / m   #计算错误率
            print("error rate:",errorRate)
            if errorRate == 0:
                break
    
        return weakClassArr
    
    #三:实现预测功能
    def adaClassify(data_sim,classfierArr): #传入测试数据和分类器
        #将所有的分类器的权重和即可得到最后结果
        m,n = data_sim.shape
        aggClassEst = np.zeros((m,1))
        for i in range(len(classfierArr)):
            classEst = stumpClassfiy(data_sim,classfierArr[i]['dimen'],classfierArr[i]['thresh'],classfierArr[i]['ineq'])
            aggClassEst += classEst*classfierArr[i]['alpha']    #累加权重
            print(aggClassEst)
        return np.sign(aggClassEst)
    
    data_X,data_Y = loadSimpData()
    # print(adaBoostTrains(data_X,np.array([data_Y]).T))
    classfierArr = adaBoostTrains(data_X,np.array([data_Y]).T)
    print(adaClassify(np.array([[0,0]]),classfierArr))
    print(adaClassify(np.array([[5,5],[0,0]]),classfierArr))
    View Code
  • 相关阅读:
    RN-Android构建失败:Caused by: org.gradle.api.ProjectConfigurationException: A problem occurred configuring root project 'AwesomeProject'.
    Android更新包下载成功后不出现安装界面
    真机调试: The application could not be installed: INSTALL_FAILED_TEST_ONLY
    react native 屏幕尺寸转换
    Android Studio生成签名文件,自动签名,以及获取SHA1和MD5值
    React Native安卓真机调试
    git提交代码报错Permission denied, please try again
    The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.
    命令行设置快捷命令
    Linux 常用指令
  • 原文地址:https://www.cnblogs.com/ssyfj/p/13388408.html
Copyright © 2011-2022 走看看