机器学习实战:集成方法 - AdaBoost

机器学习实战:集成方法 - AdaBoost

一、集成方法

1、集成方法 概述

  • 集成方法ensemble method(元算法: meta algorithm)概念:是对其他算法进行组合的一种形式。

  • 通俗来说: 当做重要决定时,大家可能都会考虑吸取多个专家而不只是一个人的意见。 机器学习处理问题时又何尝不是如此? 这就是集成方法背后的思想。

  • 集成方法:

  1. 投票选举(bagging: 自举汇聚法 bootstrap aggregating): 是基于数据随机重抽样分类器构造的方法
  2. 再学习(boosting): 是基于所有分类器的加权求和的方法

2、集成方法 场景

目前 bagging 方法最流行的版本是: 随机森林(random forest)
选男友:美女选择择偶对象的时候,会问几个闺蜜的建议,最后选择一个综合得分最高的一个作为男朋友

目前 boosting 方法最流行的版本是: AdaBoost
追女友:3个帅哥追同一个美女,第1个帅哥失败->(传授经验:姓名、家庭情况) 第2个帅哥失败->(传授经验:兴趣爱好、性格特点) 第3个帅哥成功

bagging 和 boosting 区别是什么?

  1. bagging 是一种与 boosting 很类似的技术, 所使用的多个分类器的类型(数据量和特征量)都是一致的。
  2. bagging 是由不同的分类器(1.数据随机化 2.特征随机化)经过训练,综合得出的出现最多分类结果;boosting 是通过调整已有分类器错分的那些数据来获得新的分类器,得出目前最优的结果。
  3. bagging 中的分类器权重是相等的;而 boosting 中的分类器加权求和,所以权重并不相等,每个权重代表的是其对应分类器在上一轮迭代中的成功度。

二、AdaBoost

1、AdaBoost 概述

能否使用弱分类器和多个实例来构建一个强分类器?这是一个非常有趣的理论问题。这里的 “弱”意味着分类器的性能比随机猜测要略好,但是也不会好太多。这就是说,在二分类情况下弱分类器的错误率会高于50%,而“强”分类器的错误率将会低很多。AdaBoost (adaptive boosting: 自适应 boosting) 算法即脱胎于上述理论问题。

2、AdaBoost 原理

工作原理

训练数据中的每 个样本,并赋予其一个权重,这些权重构成了向量D。一开始,这些权重都初始化成相等值。首 先在训练数据上训练出一个弱分类器并计算该分类器的错误率,然后在同一数据集上再次训练弱 分类器。在分类器的第二次训练当中,将会重新调整每个样本的权重,其中第一次分对的样本的 权重将会降低,而第一次分错的样本的权重将会提高。为了从所有弱分类器中得到终的分类结 果,AdaBoost为每个分类器都分配了一个权重值alpha,这些alpha值是基于每个弱分类器的错误 率进行计算的。其中,错误率ε的定义为:
在这里插入图片描述
而alpha的计算公式如下: 在这里插入图片描述

在这里插入图片描述
计算出alpha值之后,可以对权重向量D进行更新,以使得那些正确分类的样本的权重降低而 错分样本的权重升高。D的计算方法如下。 如果某个样本被正确分类,那么该样本的权重更改为:
在这里插入图片描述
而如果某个样本被错分,那么该样本的权重更改为:
在这里插入图片描述
在计算出D之后,AdaBoost又开始进入下一轮迭代。AdaBoost算法会不断地重复训练和调整 权重的过程,直到训练错误率为0或者弱分类器的数目达到用户的指定值为止。

开发流程

  1. 收集数据:可以使用任意方法
  2. 准备数据:依赖于所使用的弱分类器类型,本章使用的是单层决策树,这种分类器可以处理任何数据类型。 当然也可以使用任意分类器作为弱分类器,第2章到第6章中的任一分类器都可以充当弱分类器。作为弱分类器,简单分类器的效果更好。
  3. 分析数据:可以使用任意方法。
  4. 训练算法:AdaBoost 的大部分时间都用在训练上,分类器将多次在同一数据集上训练弱分类器。
  5. 测试算法:计算分类的错误率。
  6. 使用算法:通SVM一样,AdaBoost 预测两个类别中的一个。如果想把它应用到多个类别的场景,那么就要像多类 SVM 中的做法一样对 AdaBoost 进行修改。

算法特点

  • 优点:泛化(由具体的、个别的扩大为一般的)错误率低,易编码,可以应用在大部分分类器上,无参数调节。
  • 缺点:对离群点敏感。
  • 适用数据类型:数值型和标称型数据。

3、AdaBoost 项目案例: 马疝病的预测

完整代码:https://blog.csdn.net/qq_45556599/article/details/103500459

项目流程图(来源:https://github.com/apachecn/AiLearning/blob/master/docs/ml/7.%E9%9B%86%E6%88%90%E6%96%B9%E6%B3%95-%E9%9A%8F%E6%9C%BA%E6%A3%AE%E6%9E%97%E5%92%8CAdaBoost.md)
在这里插入图片描述
单层决策树(decision stump,也称决策树桩):
是一种简单的决策树。前面我们已经介绍了决策树的工作原理,接下来将构建一个单层决策树,而它仅基于单个特征来做决策。由于这棵树只 有一次分裂过程,因此它实际上就是一个树桩。

项目概述

预测患有疝气病的马的存活问题,这里的数据包括368个样本和28个特征,疝气病是描述马胃肠痛的术语,然而,这种病并不一定源自马的胃肠问题,其他问题也可能引发疝气病,该数据集中包含了医院检测马疝气病的一些指标,有的指标比较主观,有的指标难以测量,例如马的疼痛级别。另外,除了部分指标主观和难以测量之外,该数据还存在一个问题,数据集中有30%的值是缺失的。

开发流程

收集数据:提供的文本文件
准备数据:确保类别标签是+1和-1,而非1和0
分析数据:统计分析
训练算法:在数据上,利用 adaBoostTrainDS() 函数训练出一系列的分类器
测试算法:我们拥有两个数据集。在不采用随机抽样的方法下,我们就会对 AdaBoost 和 Logistic 回归的结果进行完全对等的比较
使用算法:观察该例子上的错误率。不过,也可以构建一个 Web 网站,让驯马师输入马的症状然后预测马是否会死去

收集数据:提供的文本文件

训练数据:horseColicTraining.txt
测试数据:horseColicTest.txt

2.000000	1.000000	38.500000	66.000000	28.000000	3.000000	3.000000	0.000000	2.000000	5.000000	4.000000	4.000000	0.000000	0.000000	0.000000	3.000000	5.000000	45.000000	8.400000	0.000000	0.000000	-1.000000
1.000000	1.000000	39.200000	88.000000	20.000000	0.000000	0.000000	4.000000	1.000000	3.000000	4.000000	2.000000	0.000000	0.000000	0.000000	4.000000	2.000000	50.000000	85.000000	2.000000	2.000000	-1.000000
2.000000	1.000000	38.300000	40.000000	24.000000	1.000000	1.000000	3.000000	1.000000	3.000000	3.000000	1.000000	0.000000	0.000000	0.000000	1.000000	1.000000	33.000000	6.700000	0.000000	0.000000	1.000000

准备数据:确保类别标签是+1和-1,而非1和0

def loadDataSet(fileName):
    # get number of fields
    numFeat = len(open(fileName).readline().split('\t'))
    dataArr = []
    labelArr = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr = []
        curLine = line.strip().split('\t')
        for i in range(numFeat - 1):
            lineArr.append(float(curLine[i]))
        dataArr.append(lineArr)
        labelArr.append(float(curLine[-1]))
    return dataArr, labelArr

分析数据:统计分析

过拟合(overfitting, 也称为过学习)

  • 发现测试错误率在达到一个最小值之后有开始上升,这种现象称为过拟合。
    在这里插入图片描述
  • 通俗来说:就是把一些噪音数据也拟合进去的,如下图。在这里插入图片描述
    训练算法:在数据上,利用 adaBoostTrainDS() 函数训练出一系列的分类器
def buildStump(dataArr, labelArr, D):
    """buildStump(得到决策树的模型)
    Args:
        dataArr   特征标签集合
        labelArr  分类标签集合
        D         最初的样本的所有特征权重集合
    Returns:
        bestStump    最优的分类器模型
        minError     错误率
        bestClasEst  训练后的结果集
    """
    # 转换数据
    dataMat = mat(dataArr)
    labelMat = mat(labelArr).T
    # m行 n列
    m, n = shape(dataMat)

    # 初始化数据
    numSteps = 10.0
    bestStump = {}
    bestClasEst = mat(zeros((m, 1)))
    # 初始化的最小误差为无穷大
    minError = inf

    # 循环所有的feature列,将列切分成 若干份,每一段以最左边的点作为分类节点
    for i in range(n):
        rangeMin = dataMat[:, i].min()
        rangeMax = dataMat[:, i].max()
        # print 'rangeMin=%s, rangeMax=%s' % (rangeMin, rangeMax)
        # 计算每一份的元素个数
        stepSize = (rangeMax - rangeMin) / numSteps
        # 例如: 4=(10-1)/2   那么  1-4(-1次)   1(0次)  1+1*4(1次)   1+2*4(2次)
        # 所以: 循环 -1/0/1/2
        for j in range(-1, int(numSteps) + 1):
            # go over less than and greater than
            for inequal in ['lt', 'gt']:
                # 如果是-1,那么得到rangeMin-stepSize; 如果是numSteps,那么得到rangeMax
                threshVal = (rangeMin + float(j) * stepSize)
                # 对单层决策树进行简单分类,得到预测的分类值
                predictedVals = stumpClassify(dataMat, i, threshVal, inequal)
                # print predictedVals
                errArr = mat(ones((m, 1)))
                # 正确为0,错误为1
                errArr[predictedVals == labelMat] = 0
                # 计算 平均每个特征的概率0.2*错误概率的总和为多少,就知道错误率多高
                # 例如: 一个都没错,那么错误率= 0.2*0=0 , 5个都错,那么错误率= 0.2*5=1, 只错3个,那么错误率= 0.2*3=0.6
                weightedError = D.T * errArr
                '''
                dim            表示 feature列
                threshVal      表示树的分界值
                inequal        表示计算树左右颠倒的错误率的情况
                weightedError  表示整体结果的错误率
                bestClasEst    预测的最优结果
                '''
                # print("split: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (i, threshVal, inequal, weightedError))
                if weightedError < minError:
                    minError = weightedError
                    bestClasEst = predictedVals.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = threshVal
                    bestStump['ineq'] = inequal

    # bestStump 表示分类器的结果,在第几个列上,用大于/小于比较,阈值是多少
    return bestStump, minError, bestClasEst


def adaBoostTrainDS(dataArr, labelArr, numIt=40):
    """adaBoostTrainDS(adaBoost训练过程放大)
    Args:
        dataArr   特征标签集合
        labelArr  分类标签集合
        numIt     迭代次数(用户指定)
    Returns:
        weakClassArr  弱分类器的集合
        aggClassEst   预测的分类结果值
    """
    weakClassArr = []
    m = shape(dataArr)[0]
    # 初始化 D,设置每行数据的样本的所有特征权重集合,平均分为m份
    D = mat(ones((m, 1)) / m)
    aggClassEst = mat(zeros((m, 1)))
    for i in range(numIt):
        # 得到决策树的模型
        bestStump, error, classEst = buildStump(dataArr, labelArr, D)

        # alpha 目的主要是计算每一个分类器实例的权重(加和就是分类结果)
        # 计算每个分类器的 alpha 权重值
        alpha = float(0.5 * log((1.0 - error) / max(error, 1e-16)))  # 防止错误率为0时溢出
        bestStump['alpha'] = alpha
        # store Stump Params in Array
        weakClassArr.append(bestStump)

        # print "alpha=%s, classEst=%s, bestStump=%s, error=%s " % (alpha, classEst.T, bestStump, error)
        # 分类正确:乘积为1,不会影响结果,-1主要是下面求e的-alpha次方
        # 分类错误:乘积为 -1,结果会受影响,所以也乘以 -1
        expon = multiply(-1 * alpha * mat(labelArr).T, classEst)
        # print '\n'
        # print 'labelArr=', labelArr
        # print 'classEst=', classEst.T
        # print '\n'
        # print '乘积: ', multiply(mat(labelArr).T, classEst).T
        # 判断正确的,就乘以-1,否则就乘以1, 为什么? 书上的公式。
        # print '(-1取反)预测值expon=', expon.T
        # 计算e的expon次方,然后计算得到一个综合的概率的值
        # 结果发现: 判断错误的样本,D对于的样本权重值会变大。
        D = multiply(D, exp(expon))
        D = D / D.sum()
        # print("D: ", D.T)
        # print '\n'

        # 预测的分类结果值,在上一轮结果的基础上,进行加和操作
        # print('当前的分类结果:', alpha * classEst.T)
        aggClassEst += alpha * classEst
        # print("叠加后的分类结果aggClassEst: ", aggClassEst.T)
        # sign 判断正为1, 0为0, 负为-1,通过最终加和的权重值,判断符号。
        # 结果为:错误的样本标签集合,因为是 !=,那么结果就是0 正, 1 负
        aggErrors = multiply(sign(aggClassEst) != mat(labelArr).T, ones((m, 1)))
        errorRate = aggErrors.sum() / m
        print("total error=%s " % (errorRate))
        if errorRate == 0.0:
            break
    return weakClassArr, aggClassEst

发现: alpha (模型权重)目的主要是计算每一个分类器实例的权重(加和就是分类结果) 分类的权重值:最大的值= alpha的加和,最小值=-最大值 D (样本权重)的目的是为了计算错误概率: weightedError = D.T*errArr,求最佳分类器样本的权重值:如果一个值误判的几率越小,那么 D 的样本权重越小

测试算法:我们拥有两个数据集。在不采用随机抽样的方法下,我们就会对 AdaBoost 和 Logistic 回归的结果进行完全对等的比较。

def adaClassify(datToClass, classifierArr):
    # do stuff similar to last aggClassEst in adaBoostTrainDS
    dataMat = mat(datToClass)
    m = shape(dataMat)[0]
    aggClassEst = mat(zeros((m, 1)))

    # 循环 多个分类器
    for i in range(len(classifierArr)):
        # 前提: 我们已经知道了最佳的分类器的实例
        # 通过分类器来核算每一次的分类结果,然后通过alpha*每一次的结果 得到最后的权重加和的值。
        classEst = stumpClassify(dataMat, classifierArr[i]['dim'], classifierArr[i]['thresh'], classifierArr[i]['ineq'])
        aggClassEst += classifierArr[i]['alpha'] * classEst
        # print aggClassEst
    return sign(aggClassEst)

使用算法:观察该例子上的错误率。不过,也可以构建一个 Web 网站,让驯马师输入马的症状然后预测马是否会死去。

在这里插入图片描述

三、要点补充:非均衡分类问题

在分类器训练时,正例数目和反例数目不相等(相差很大)。或者发生在正负例分类错误的代价不同的时候。

  • 判断马是否能继续生存(不可误杀)
  • 过滤垃圾邮件(不可漏判)
  • 不能放过传染病的人
  • 不能随便认为别人犯罪

具体可参考此链接

1、其他分类性能度量指标:正确率、召回率及 ROC曲线

混淆矩阵

在机器学习中,有一个普遍适用的称为混淆矩阵(confusion matrix)的工具,它可以帮助更好地了解分类中正确和错误的情况。
在这里插入图片描述
利用混淆矩阵就可以更好地理解分类中的错误了。如果矩阵中的非对角元素均为0,就会得到一个完美的分类器。

接下来,我们考虑另外一个混淆矩阵,这次的矩阵只针对一个简单的二类问题。在表7-3中, 给出了该混淆矩阵。在这个二类问题中,如果将一个正例判为正例,那么就可以认为产生了一个 真正例(True Positive,TP,也称真阳);如果对一个反例正确地判为反例,则认为产生了一个真反例(True Negative,TN,也称真阴)。相应地,另外两种情况则分别称为伪反例(False Negative, FN,也称假阴)和伪正例(False Positive,FP,也称假阳)。这4种情况如表7-3所示。
在这里插入图片描述
在分类中,当某个类别的重要性高于其他类别时,我们就可以利用上述定义来定义出多个比错 误率更好的新指标。第一个指标是正确率(Precision),它等于TP/(TP+FP),给出的是预测为正例的样本中的真正正例的比例。第二个指标是召回率(Recall),它等于TP/(TP+FN),给出的是预测为正例的真实正例占所有真实正例的比例。在召回率很大的分类器中,真正判错的正例的数目并不多。

我们可以很容易构造一个高正确率或高召回率的分类器,但是很难同时保证两者成立。如果 将任何样本都判为正例,那么召回率达到百分之百而此时正确率很低。构建一个同时使正确率和召回率大的分类器是具有挑战性的。

ROC曲线

另一个用于度量分类中的非均衡性的工具是ROC曲线(ROC curve),ROC代表接收者操作特征(receiver operating characteristic)。
在这里插入图片描述
在图7-3的ROC曲线中,给出了两条线,一条虚线一条实线。图中的横轴是伪正例的比例(假阳率=FP/(FP+TN))说白了就是假的被分到真的概率,而纵轴是真正例的比例(真阳率=TP/(TP+FN))说白了就是真的被分到假的概率,ROC曲线给出的是当阈值变化时假阳率和真阳率的变化情况。左下角的点所对应的是将所有样例判为反例的情况,而右上角的点对应的则是将所有样例判为正例的情况。虚线给出的是随机猜测的结果曲线。

ROC曲线不但可以用于比较分类器,还可以基于成本效益(cost-versus-benefit)分析来做出决策。由于在不同的阈值下,不同的分类器的表现情况可能各不相同,因此以某种方式将它们组合起来或许会更有意义。如果只是简单地观察分类器的错误率,那么我们就难以得到这种更深入 的洞察效果了。

在理想的情况下,最佳的分类器应该尽可能地处于左上角,这就意味着分类器在假阳率很低的同时获得了很高的真阳率。例如在垃圾邮件的过滤中,这就相当于过滤了所有的垃圾邮件,但没有将任何合法邮件误识为垃圾邮件而放入垃圾邮件的文件夹中。

对不同的ROC曲线进行比较的一个指标是曲线下的面积(Area Unser the Curve,AUC)。AUC 给出的是分类器的平均性能值,当然它并不能完全代替对整条曲线的观察。一个完美分类器的 AUC为1.0,而随机猜测的AUC则为0.5。

为了画出ROC曲线,分类器必须提供每个样例被判为阳性或者阴性的可信程度值。尽管大多 数分类器都能做到这一点,但是通常情况下,这些值会在后输出离散分类标签之前被清除。朴素贝叶斯能够提供一个可能性,而在Logistic回归中输入到Sigmoid函数中的是一个数值。在 AdaBoost和SVM中,都会计算出一个数值然后输入到sign()函数中。所有的这些值都可以用于 衡量给定分类器的预测强度。为了创建ROC曲线,首先要将分类样例按照其预测强度排序。先从排名低的样例开始,所有排名更低的样例都被判为反例,而所有排名更高的样例都被判为正例。 该情况的对应点为<1.0,1.0>。然后,将其移到排名次低的样例中去,如果该样例属于正例,那么对真阳率进行修改;如果该样例属于反例,那么对假阴率进行修改。

ROC曲线的绘制及AUC计算函数:

def plotROC(predStrengths, classLabels):
    """plotROC(打印ROC曲线,并计算AUC的面积大小)
    Args:
        predStrengths  最终预测结果的权重值
        classLabels    原始数据的分类结果集
    """
    # print('predStrengths=', predStrengths)
    # print('classLabels=', classLabels)

    import matplotlib.pyplot as plt
    # variable to calculate AUC
    ySum = 0.0
    # 对正样本的进行求和
    numPosClas = sum(array(classLabels) == 1.0)
    # 正样本的概率
    yStep = 1 / float(numPosClas)
    # 负样本的概率
    xStep = 1 / float(len(classLabels) - numPosClas)
    # argsort函数返回的是数组值从小到大的索引值
    # get sorted index, it's reverse
    sortedIndicies = predStrengths.argsort()
    # 测试结果是否是从小到大排列
    # print('sortedIndicies=', sortedIndicies, predStrengths[0, 176], predStrengths.min(), predStrengths[0, 293],
    #      predStrengths.max())

    # 开始创建模版对象
    fig = plt.figure()
    fig.clf()
    ax = plt.subplot(111)
    # cursor光标值
    cur = (1.0, 1.0)
    # loop through all the values, drawing a line segment at each point
    for index in sortedIndicies.tolist()[0]:
        if classLabels[index] == 1.0:
            delX = 0
            delY = yStep
        else:
            delX = xStep
            delY = 0
            ySum += cur[1]
        # draw line from cur to (cur[0]-delX, cur[1]-delY)
        # 画点连线 (x1, x2, y1, y2)
        # print(cur[0], cur[0] - delX, cur[1], cur[1] - delY)
        ax.plot([cur[0], cur[0] - delX], [cur[1], cur[1] - delY], c='b')
        cur = (cur[0] - delX, cur[1] - delY)
    # 画对角的虚线线
    ax.plot([0, 1], [0, 1], 'b--')
    plt.xlabel('False positive rate')
    plt.ylabel('True positive rate')
    plt.title('ROC curve for AdaBoost horse colic detection system')
    # 设置画图的范围区间 (x1, x2, y1, y2)
    ax.axis([0, 1, 0, 1])
    plt.show()
    '''
    参考说明:http://blog.csdn.net/wenyusuran/article/details/39056013
    为了计算 AUC ,我们需要对多个小矩形的面积进行累加。
    这些小矩形的宽度是xStep,因此可以先对所有矩形的高度进行累加,最后再乘以xStep得到其总面积。
    所有高度的和(ySum)随着x轴的每次移动而渐次增加。
    '''
    print("the Area Under the Curve is: ", ySum * xStep)

在这里插入图片描述
在这里插入图片描述
在50个弱分类器下的ROC:在这里插入图片描述
在这里插入图片描述

2、基于代价函数的分类器决策控制

除了调节分类器的阈值之外,我们还有一些其他可以用于处理非均衡分类代价的方法,其中 的一种称为代价敏感的学习(cost-sensitive learning)。考虑表7-4中的代价矩阵,第一张表给出的 是到目前为止分类器的代价矩阵(代价不是0就是1)。我们可以基于该代价矩阵计算其总代价: TP0+FN1+FP1+TN0。接下来我们考虑下面的第二张表,基于该代价矩阵的分类代价的计算 公式为:TP*(-5)+FN1+FP50+TN*0。采用第二张表作为代价矩阵时,两种分类错误的代价是 不一样的。类似地,这两种正确分类所得到的收益也不一样。如果在构建分类器时,知道了这些 代价值,那么就可以选择付出小代价的分类器。

在分类算法中,我们有很多方法可以用来引入代价信息。在AdaBoost中,可以基于代价函数 来调整错误权重向量D。在朴素贝叶斯中,可以选择具有小期望代价而不是大概率的类别作 为后的结果。在SVM中,可以在代价函数中对于不同的类别选择不同的参数C。上述做法就会 给较小类更多的权重,即在训练时,小类当中只允许更少的错误。
在这里插入图片描述

3、处理非均衡问题的数据抽样方法

另外一种针对非均衡问题调节分类器的方法,就是对分类器的训练数据进行改造。这可以通 过欠抽样(undersampling)或者过抽样(oversampling)来实现。过抽样意味着复制样例,而欠 抽样意味着删除样例。不管采用哪种方式,数据都会从原始形式改造为新形式。抽样过程则可以 通过随机方式或者某个预定方式来实现。
通常也会存在某个罕见的类别需要我们来识别,比如在信用卡欺诈当中。如前所述,正例类 别属于罕见类别。我们希望对于这种罕见类别能尽可能保留更多的信息,因此,我们应该保留正 例类别中的所有样例,而对反例类别进行欠抽样或者样例删除处理。这种方法的一个缺点就在于 要确定哪些样例需要进行剔除。但是,在选择剔除的样例中可能携带了剩余样例中并不包含的有 价值信息。
上述问题的一种解决办法,就是选择那些离决策边界较远的样例进行删除。假定我们有一个 数据集,其中有50例信用卡欺诈交易和5000例合法交易。如果我们想要对合法交易样例进行欠抽 样处理,使得这两类数据比较均衡的话,那么我们就需要去掉4950个样例,而这些样例中可能包 含很多有价值的信息。这看上去有些极端,因此有一种替代的策略就是使用反例类别的欠抽样和 正例类别的过抽样相混合的方法。
要对正例类别进行过抽样,我们可以复制已有样例或者加入与已有样例相似的点。一种方法 是加入已有数据点的插值点,但是这种做法可能会导致过拟合的问题。

四、集成方法 小结

集成方法通过组合多个分类器的分类结果,获得了比简单的单分类器更好的分类结果。有一些利用不同分类器的集成方法,但是本章只介绍了那些利用同一类分类器的集成方法。

多个分类器组合可能会进一步凸显出单分类器的不足,比如过拟合问题。如果分类器之间差别显著,那么多个分类器组合就可能会缓解这一问题。分类器之间的差别可以是算法本身或者是应用于算法上的数据的不同。

两种集成方法是bagging和boosting。在bagging中,是通过随机抽样的替换方式,得到了与原始数据集规模一样的数据集。而boosting在bagging的思路上更进了一步,它在数据集上顺序应用了多个不同的分类器。另一个成功的集成方法就是随机森林,但是由于随机森林不如AdaBoost流行,所以本书并没有对它进行介绍。

本章介绍了boosting方法中流行的一个称为AdaBoost的算法。AdaBoost以弱学习器作为基分类器,并且输入数据,使其通过权重向量进行加权。在第一次迭代当中,所有数据都等权重。 但是在后续的迭代当中,前次迭代中分错的数据的权重会增大。这种针对错误的调节能力正是 AdaBoost的长处。

本章以单层决策树作为弱学习器构建了AdaBoost分类器。实际上,AdaBoost函数可以应用于任意分类器,只要该分类器能够处理加权数据即可。AdaBoost算法十分强大,它能够快速处理其他分类器很难处理的数据集。

非均衡分类问题是指在分类器训练时正例数目和反例数目不相等(相差很大)。该问题在错分正例和反例的代价不同时也存在。本章不仅考察了一种不同分类器的评价方法——ROC曲线, 还介绍了正确率和召回率这两种在类别重要性不同时,度量分类器性能的指标。

本章介绍了通过过抽样和欠抽样方法来调节数据集中的正例和反例数目。另外一种可能更好的非均衡问题的处理方法,就是在训练分类器时将错误的代价考虑在内。

资料来源

https://github.com/apachecn/AiLearning
https://github.com/apachecn/AiLearning/tree/master/docs/ml
机器学习实战(作者: Peter Harrington 出版社: 人民邮电出版社原作名: Machine Learning in Action译者: 李锐 / 李鹏 / 曲亚东 / 王斌 )

发布了112 篇原创文章 · 获赞 10 · 访问量 2925

猜你喜欢

转载自blog.csdn.net/qq_45556599/article/details/103499340