关闭

adaBoost

标签: python机器学习adaBoost
217人阅读 评论(0) 收藏 举报
分类:
# -*-coding:utf-8-*-
'''
Adaboost
'''
from __future__ import division 
import numpy as np

def LoadSimpleData():
    dataMat = np.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 dataMat,classLabels

def loadDataSet(fileName):
    '''
        加载数据
    '''
    f = open(fileName)
    _numFeat = len(f.readline().split('\t'))
    dataMat = []
    labelMat = []
    for _line_ in f.readlines():
        _lineArr = []
        _curLine = _line_.strip().split('\t')
        for i in range(_numFeat - 1):
            _lineArr.append(float(_curLine[i]))
        dataMat.append(_lineArr)
        labelMat.append(float(_curLine[-1]))
    return dataMat,labelMat
    
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):
    '''
        数据集 | 特征 | 阈值 | 分类
        通过阈值比较对数据分类,以1和-1表示分类值返回
    '''
    retArray = np.ones((np.shape(dataMatrix)[0],1))   # 返回数组初始化为全1
    if threshIneq == 'lt':
        # >阈值为1;<=阈值为-1
        retArray[dataMatrix[:,dimen] <= threshVal] = -1.0
    else:
        # >阈值为-1;<=阈值为1
        retArray[dataMatrix[:,dimen] > threshVal] = -1.0
    return retArray

def buildStump(dataArr,classLabels,D):
    '''
        找错误率最小的决策树
        将最小错误率minError设为+无穷
        对数据集中的每一个特征(第一层循环):
            对每个步长(第二层循环):
                对每个不等号(第三层循环):
                    建立一棵单层决策树并利用加权数据集对它进行测试
                    如果错误率低于minError,则将当前单层决策树设为最佳单层决策树
    '''
    _dataMatrix = np.mat(dataArr)
    _labelMat = np.mat(classLabels).T
    m,n = np.shape(_dataMatrix)
    _numSteps = 10.0 # 按步长与训练数据比较,
    bestStump = {} # 存储给定权重向量D时所得到的最佳单层决策树
    bestClassEst = np.mat(np.zeros((m,1)))  
    minError = np.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_)  # 与阈值相比后的1.-1分类向量
                _errArr = np.mat(np.ones((m,1)))    # 初始化误差矩阵为全1
                _errArr[_predictedVals == _labelMat] = 0    # 预测分类与实际类,正确=0
                _weightedError = D.T * _errArr # 误差率 e
                if _weightedError < minError:   # 选择最小错误率的决策树
                    minError = _weightedError
                    bestClassEst = _predictedVals.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = _threshVal
                    bestStump['ineq'] = _inequal_
    return bestStump,minError,bestClassEst  # 返回构建的单层决策树,最小的错误率和分类向量

def adaBoostTrainDS(dataArr,classLabels,numIt=40):
    '''
        基于当成决策树的AdaBoost训练过程
    '''
    weakClassArr=[]
    m,n = np.shape(dataArr)
    _D = np.mat(np.ones((m,1))/m)   # 训练数据权重初始为全1
    _aggClassEst = np.mat(np.zeros((m,1)))  # 按照权重计算出每个数据的分类估计累计值
    for i in range(numIt):  # 循环,直到最大循环次数或错误率为0
        '''
                    构建一个单层决策树
                    返回的是利用D而得到的具有最小错误率的单层决策树,最小的误差率,估计的类别向量
        '''
        _bestStump, _error, _classEst = buildStump(dataArr,classLabels,_D)
        #print "D: ",_D.T
        _alpha = float(0.5 * np.log((1.0-_error) / max(_error,1e-16))) # 根据错误率计算分类器输出结果的权重
        _bestStump['alpha'] = _alpha    # 存储该单层决策树的权重
        weakClassArr.append(_bestStump)  
        #print "classEst: ",_classEst.T
        _expon = np.multiply(-1 * _alpha * np.mat(classLabels).T,_classEst)    # 更新数据的权重分布
        _D = np.multiply(_D,np.exp(_expon))
        _D = _D/_D.sum()
           
        _aggClassEst += _alpha * _classEst  # 记录运行时的估计值  
        #print "aggClassEst: ",_aggClassEst.T
        _aggErrors = np.multiply(np.sign(_aggClassEst) != np.mat(classLabels).T,np.ones((m,1))) # 
        errorRate = _aggErrors.sum()/m
        print "total error: ",errorRate,"\n"
        if errorRate == 0.0:
            break
    return weakClassArr

def adaClassify(datToClass,classifierArr):
    '''
        带分类样例  | 多个弱分类器组成的数组
        利用训练出的多个弱分类器进行分类
    '''
    _dataMatrix = np.mat(datToClass)
    m,n = np.shape(_dataMatrix) 
    _aggClassEst = np.mat(np.zeros((m,1)))   # 全0列向量,存储累计的分类结果
    for i in range(len(classifierArr)):     #  对每一训练好的弱分类器
        classEst = stumpClassify(_dataMatrix,classifierArr[i]['dim'],classifierArr[i]['thresh'],classifierArr[i]['ineq'])    # 类别估计值
        _aggClassEst += classifierArr[i]['alpha']*classEst
    return np.sign(_aggClassEst)
            
dataArr,labelArr = loadDataSet('horseColicTraining2.txt')
classifierArr = adaBoostTrainDS(dataArr,labelArr,10)
testArr,testLabelArr = loadDataSet('horseColicTest2.txt')
predict = adaClassify(testArr,classifierArr)
errArr = np.mat(np.ones((67,1)))
print errArr[predict != np.mat(testLabelArr).T].sum()

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:24593次
    • 积分:543
    • 等级:
    • 排名:千里之外
    • 原创:31篇
    • 转载:1篇
    • 译文:0篇
    • 评论:1条
    文章分类
    最新评论