Machine Learning in Action -- AdaBoost

初始的想法就是,结合不同的分类算法来给出综合的结果,会比较准确一些 
称为ensemble methods or meta-algorithms,集成方法或元算法

集成方法有很多种,可以是不同算法之间的,也可以是同一个算法但不同参数设置之间的,也可以是将数据集分成多分给不同的分类器之间的 
总的来说,有3个维度可以进行集成,算法,算法参数和数据集

下面简单介绍两种比较流行的元算法思路,

1. Building classifiers from randomly resampled data: bagging

bagging又称为bootstrap aggregating 
想法比较简单,对大小为n的训练集做n次放回随机抽样,形成新的大小仍然为n的训练集 
因为是放回随机抽样,新的训练集中可能有重复,某些训练集中的样本中新的训练集中也会没有 
用这个方法,产生s个新的训练集,对同一个分类算法可以产生s个不同参数的分类器 
使用时,让s个分类器,多数投票表决来决定最终的分类结果

比较典型的bagging算法,如随机森林(random forest) 
首先采用bootstrap取样,用产生新的训练集生成决策树,并且用在新训练集中没有抽样到样本作为测试集 
如果有S个新的训练集,就会产生S个决策树,所以称为森林 
所谓随机,首先新训练集是随机抽样产生的 
再者,在训练决策树的时候,每个树节点会随机选择m个特征(m<<M总特征数) 
参考,http://zh.wikipedia.org/wiki/%E9%9A%8F%E6%9C%BA%E6%A3%AE%E6%9E%97

2. Boosting

下面主要介绍Boosting中最流行的AdaBoost算法,这里主要介绍实现,理论参考前一篇

我们使用单层决策树,即decision stump 决策树桩作为弱分类器 
所谓decision stump,就是只对一个特征做一次划分的单节点的决策树

这个弱分类器足够简单,但是如果直接使用,基本没用, 
比如对于底下这个很简单的训练集,用一个decision stump都无法完全正确分类,试着在x轴或y轴上做一次划分

虽然无法完全正确分类,但是我们需要找到误差最小的那个decision stump 
方法很简单,在x和y的取值范围内,以一定的步长,遍历比较误差

先实现stump分类, 
dataMatrix,一行表示一个训练样本,每列表示一个特征 
dimen,表示哪个特征 
threshVal,阀值 
threshIneq,对于decision stump,只存在less than或greater than

def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):
    retArray = ones((shape(dataMatrix)[0],1))
    if threshIneq == 'lt': #lt,less than
        retArray[dataMatrix[:,dimen] <= threshVal] = -1.0 #boolean indexing
    else:
        retArray[dataMatrix[:,dimen] > threshVal] = -1.0
    return retArray

所以给定上面的参数,就是可以判断每个样本的分类是1或-1

下面给出求解最优stump分类器的算法, 
参数中有个D向量,表示样本weight 
因为这里是要找到加权样本误差最小的stump分类器

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  #inf,python中表示无穷大
    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']:    #尝试划分的方向,less than或greater than
                threshVal = (rangeMin + float(j) * stepSize)
                predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal) #进行stump分类
                errArr = mat(ones((m,1)))  #初始化误差为1
                errArr[predictedVals == labelMat] = 0  #计算误差,将分对的误差设为0
                weightedError = D.T*errArr   #计算加权误差
                if weightedError < minError: #如果小于minError,说明我们找到更优的stump分类器
                    minError = weightedError
                    bestClasEst = predictedVals.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = threshVal
                    bestStump['ineq'] = inequal
    return bestStump,minError,bestClasEst

好,现在可以给出AdaBoost算法的源码,

def adaBoostTrainDS(dataArr,classLabels,numIt=40):
    weakClassArr = []
    m = shape(dataArr)[0]  #样本数
    D = mat(ones((m,1))/m)   #初始化样本weight,所有样本权值相等为1/m
    aggClassEst = mat(zeros((m,1))) #累积分类结果
    for i in range(numIt):  #生成多少个弱分类器
        bestStump,error,classEst = buildStump(dataArr,classLabels,D) #计算最优的stump分类器
        print "D:",D.T
        alpha = float(0.5*log((1.0-error)/max(error,1e-16))) #1.计算该分类器的权值
        bestStump['alpha'] = alpha
        weakClassArr.append(bestStump)
        print "classEst: ",classEst.T
        expon = multiply(-1*alpha*mat(classLabels).T,classEst)
        D = multiply(D,exp(expon))   #2.更新样本权值
        D = D/D.sum()
        aggClassEst += alpha*classEst   #3.更新累积分类结果
        print "aggClassEst: ",aggClassEst.T
        aggErrors = multiply(sign(aggClassEst) !=   #计算累积分类误差
                    mat(classLabels).T,ones((m,1)))
        errorRate = aggErrors.sum()/m
        print "total error: ",errorRate,"\n"
        if errorRate == 0.0: break   #4.误差为0,算法结束
    return weakClassArr

其中,

1. 计算分类器权值的公式为,

max(error,1e-16),这个是为了防止error为0

2. 更新样本权值的公式为,

即判断正确时,减小权值,而错误时,增大权值

expon = multiply(-1*alpha*mat(classLabels).T,classEst) 
-alpha×classLabel×classEst,即如果分类正确,classLable=classEst,仍然得到-alpha,否则得到alpha

3. aggClassEst

因为我们最终在分类时,是用多个弱分类器的综合结果 
所以这里每生成一个弱分类器,我们就把它的分类结果加到aggClassEst上,aggClassEst += alpha*classEst

aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1)))

用于aggClassEst是float类型,所以先使用sign转换成1,-1,0 
然后!= mat(classLabels).T,会产生一个boolean的向量 
小技巧,这里为何要乘上一个全1的向量,因为需要把boolean类型转换为int

可以在python试下,

>>> (1 == 1) *1 
1

4.最终当所有弱分类器综合误差为0时,就不需要继续迭代了

下面看看,如何用AdaBoost算法进行分类

def adaClassify(datToClass,classifierArr):
    dataMatrix = mat(datToClass)
    m = shape(dataMatrix)[0]
    aggClassEst = mat(zeros((m,1)))
    for i in range(len(classifierArr)):
        classEst = stumpClassify(dataMatrix,classifierArr[i]['dim'],\
                                classifierArr[i]['thresh'],\
                                classifierArr[i]['ineq'])
        aggClassEst += classifierArr[i]['alpha']*classEst
        print aggClassEst
    return sign(aggClassEst)

2014-08-28
时间: 2024-08-03 16:55:52

Machine Learning in Action -- AdaBoost的相关文章

Machine Learning in Action – PCA和SVD

降维技术,  首先举的例子觉得很好,因为不知不觉中天天都在做着降维的工作 对于显示器显示一个图片是通过像素点0,1,比如对于分辨率1024×768的显示器,就需要1024×768个像素点的0,1来表示,这里每个像素点都是一维,即是个1024×768维的数据.而其实眼睛真正看到的只是一副二维的图片,这里眼睛其实在不知不觉中做了降维的工作,把1024×768维的数据降到2维 降维的好处,显而易见,数据更易于显示和使用,去噪音,减少计算量,更容易理解数据  主流的降维技术,包含:  主成分分析,pri

机器学习实战(Machine Learning in Action)笔记--Chapter1:机器学习基础

Part1 分类 监督学习一般使用两种类型的目标变量:标称型(主要用于分类).数值型(主要用于回归). 非均衡分类问题 第1章 机器学习基础 专家系统 训练样本.特征.目标变量(分类问题中为类别) 训练数据和测试数据 知识表示 监督学习:分类.回归 无监督学习 将数据集合分成由类似的对象组成的多个类的过程被称为聚类 将寻找描述数据统计值的过程称之为密度估计 监督学习的用途:k-近邻算法.朴素贝叶斯算法.支持向量机.决策树.线性回归.局部加权线性回归.Ridge回归.Lasso最小回归系数估计 无

Machine Learning in Action -- Support Vector Machines

虽然SVM本身算法理论,水比较深,很难懂 但是基本原理却非常直观易懂,就是找到与训练集中支持向量有最大间隔的超平面 形式化的描述: 其中需要满足m个约束条件,m为数据集大小,即数据集中的每个数据点function margin都是>=1,因为之前假设所有支持向量,即离超平面最近的点,的function margin为1 对于这种有约束条件的最优化问题,用拉格朗日定理,于是得到如下的形式, 现在我们的目的就是求出最优化的m个拉格朗日算子,因为通过他们我们可以间接的算出w和b,从而得到最优超平面 考

Machine Learning in Action -- 回归

机器学习问题分为分类和回归问题  回归问题,就是预测连续型数值,而不像分类问题,是预测离散的类别 至于这类问题为何称为回归regression,应该就是约定俗成,你也解释不通  比如为何logistic regression叫逻辑回归,明明解决的是分类问题,而且和逻辑没有半点关系 谈到回归,最简单的就是线性回归 用直线去拟合数据点, 我们通常用平方误差来作为目标函数,称为最小二乘(ordinary least squares),参考AndrewNG的讲义 如何解这个问题,可以用梯度下降,但其实更

Machine Learning in Action -- Logistic regression

这个系列,重点关注如何实现,至于算法基础,参考Andrew的公开课 相较于线性回归,logistic回归更适合用于分类 因为他使用Sigmoid函数,因为分类的取值是0,1 对于分类,最完美和自然的函数,当然是Heaviside step function,即0-1阶跃函数,但是这个函数中数学上有时候比较难处理 所以用Sigmoid函数来近似模拟阶跃函数, 可以看到Sigmoid在增大坐标尺度后,已经比较接近于阶跃函数 其中, 而logistic回归就是要根据训练集找到,最优的w向量 下面就通过

Machine Learning in Action -- FP-growth

要解决的问题,频繁项集 最暴力的方法,就是遍历所有的项集组合,当然计算量过大  最典型的算法apriori, 算法核心思想,当一个集合不是频繁项集,那么它的超集也一定不是频繁项集  这个结论是很明显的,基于这样的思路,可以大大减少频繁项集的候选项  因为你只要发现一个集合非频繁项集,那么他所有的超集都可以忽略 但apriori算法的问题是,计算每个候选项的出现频率的时候都需要遍历整个数据集,这个明显是低效的  很自然的想法,就是否有办法可以尽量少的遍历数据集?比如遍历一遍就可以得到所有的项集的出

A Gentle Introduction to the Gradient Boosting Algorithm for Machine Learning

A Gentle Introduction to the Gradient Boosting Algorithm for Machine Learning by Jason Brownlee on September 9, 2016 in XGBoost 0 0 0 0   Gradient boosting is one of the most powerful techniques for building predictive models. In this post you will d

Learning Machine Learning, Part 3: Application

This post features a basic introduction to machine learning (ML). You don't need any prior knowledge about ML to get the best out of this article. Before getting started, let's address this question: "Is ML so important that I really need to read thi

Mapreduce for Machine Learning

MapReduce for Machine Learning Baofeng Zhang 369447122@qq.com  转载请注明出处:http://blog.csdn.net/zbf8441372   Abstract We are at the beginning of the multicoreera. Computers will have increasingly many cores (processors), but there isstill no good program