机器学习day12 机器学习实战adaboost集成方法与重新进行疝马病的预测

Posted flowertree花树

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器学习day12 机器学习实战adaboost集成方法与重新进行疝马病的预测相关的知识,希望对你有一定的参考价值。

今天终于完成了分类器的学习,SVM基本不怎么会,很是头疼,先放一下吧,有机会问问大神讲解一下。接下来的几天进行监督学习回归部分的学习,先看看adaboost的理解。

我们再决定一个重要的事情时,往往不是听取一个人的意见,听取大家的意见,然后投票表决最终结果。这一个特点也可以应用于机器学习的算法中来,每一个人都是弱的分类器,若是指一个人的力量很小,很多人汇集在一起就构成了强分类器。好比政府的投票系统。

有一个有趣的现象,若每个人都有51%的几率选择正确,则汇集很多人的投票信息之后选择正确的人比选择错误的人多很多,我们认为多数人的选择是正确的,选择错误的人很难扳回来,因为差的人数太多了,投票的人越多,这种现象越得到加强。9个人选A,11个人选B,A和B没什么区别,9000个人选A,11000个人选B,这样A和B就差很多了,我们认为B是正确的。多个弱分类器好比多个人,分类器越多分类结果越得到加强,这样就解释了多个弱分类器可以构成强分类器。

对一组训练样本分类N次,每一次结合更新的权值。

每次听取一个分类器的意见和比重alpha的乘积,最后N个分类器的意见听取结束后最终结果作为预测结果。

每一个阈值分类器为低级分类器,每个循环选择最佳阈值分类器。

算法关键流程(写一点关键步骤,详细步骤参见博客http://www.csdn123.com/html/topnews201408/87/6287.htm或者搜索adaboost的原理与推导):

技术分享每一轮最佳阈值分类器

误差率就是被选错的样本权值之和,选择一个误差率最小的,并且误差率高于50%的不要。

然后计算这个阈值分类器在最终分类器中的权重

技术分享

em越大am越小,说明不好的分类器所占权重越小。

然后更新每个样本的权值

技术分享

接下来上代码:

step1:

读取简单测试数据:

#读取简单数据
def loadData():
    datamat = matrix([[1, 2.1], 
                    [2, 1.1], 
                    [1.3, 1], 
                    [1, 1], 
                    [2, 1]])
    lavels = [1.0, 1.0, -1.0, -1.0, 1.0]
    return datamat, lavels

step2:

单层决策树的阈值分类器分类函数和分类器选择函数:

#弱分类器分类函数
#参数:数据集 特性所在列 特性阈值 分类值为1或-1
def lowType(Data, x, num, t):
    res = ones((Data.shape[0], 1))
    if t == 'less':
        res[Data[ : ,x] <= num] = -1
    else:
        res[Data[ : ,x] > num] = -1
    return res

#训练一个低级分类器,从多个弱分类器中选出误差值最小的
def trainClassify(datas, lavel, D):
    Datamat = mat(datas)
    Lavels = mat(lavel).T
    m ,n = shape(Datamat)
    best = {}
    bestlavels = mat(ones((m, 1)))
    step = 10.0
    minerror = inf
    for i in range(n):
        minnum = Datamat[ : , i].min()
        maxnum = Datamat[ : , i].max()
        times = (maxnum - minnum) / step
        for j in range(-1, int(step) + 1):
            number = minnum + j * times
            for k in ['less', 'large']:
                r = lowType(Datamat, i, number, k)
                error = mat(ones((m, 1)))
                error[r == Lavels] = 0
                weights = error.T * D
                print "特性行:%d 特性分类值:%f 特性值选择方式:%s 误差值%f"%                (i, number, k, weights)
                if weights < minerror:
                    minerror = weights
                    bestlavels = r.copy()
                    best['row'] = i
                    best['number'] = number
                    best['types'] = k
    return best, minerror, bestlavels
step3:

adaboost训练器,每次训练一个弱分类器直到误差率0或次数限制

#adaboost训练器
def adaboostTrain(dataset, lavels, cycle = 40):
    adaboost = []
    m, n = shape(dataset)
    D = mat(ones((m, 1)) / m)
    lastlavels = zeros((m ,1))
    for i in range(cycle):
        temp, temperror, templavels = trainClassify(dataset, lavels, D)
        print "D:", D.T
        alpha = float(0.5 * log((1.0 - temperror) / max(temperror, 1e-16)))
        temp['alpha'] = alpha
        adaboost.append(temp)
        print "第%d次预测的结果:"%(i + 1), templavels.T
        e = multiply(-1 * alpha * mat(lavels).T, templavels)
        D = multiply(D, exp(e))
        D = D / D.sum()
        lastlavels += alpha * templavels
        print "高级分类器的结果:", lastlavels.T
        lasterror = multiply(sign(lastlavels) != mat(lavels).T, ones((m, 1)))
        errorRate = lasterror.sum() / m
        print "错误率为%f"%(errorRate)
        if errorRate == 0.0:
            break
    return adaboost

step4:

把训练出来的分类器用于分类测试

#分类预测,参数为测试数据和adaboost分类器
def adaboostClassify(testdata, adaboost):
    testmat = mat(testdata)
    m = shape(testmat)[0]
    classifylavels = zeros((m, 1))
    for i in range(len(adaboost)):
        templavels = lowType(testmat, adaboost[i]['row'],         adaboost[i]['number'], adaboost[i]['types'])
        classifylavels += adaboost[i]['alpha'] * templavels
        print classifylavels
    return sign(classifylavels)    

到此为止,训练器完成,我们应用与LR中疝马病的预测的难数据集实验以下效果

step5:

读取疝马病数据:

#数据加载函数
def loadDataSet(filename):
    featruenum = len(open(filename).readline().split('\t'))
    f = open(filename)
    data = []
    l = []
    for i in f.readlines():
        line = i.strip().split('\t')
        temp = []
        for arr in range(featruenum - 1):
            temp.append(float(line[arr]))
        data.append(temp)
        l.append(float(line[-1]))
    return mat(data), l

测试结果如下图:


技术分享

在数据缺失30%的情况下错误率24%左右,比LR的30%满意很多,另外在弱分类器的个数增加到一个数量后错误率稳定,之后随着分类器的增加错误率反而上升,称之为过拟合现象。

具体测试程序请参见《机器学习实战》,这里不列出来。

全部代码:

#!usr/bin/python
#coding:utf-8

#adaboost.py

import numpy
from numpy import *
import operator

#读取简单数据
def loadData():
    datamat = matrix([[1, 2.1], 
                    [2, 1.1], 
                    [1.3, 1], 
                    [1, 1], 
                    [2, 1]])
    lavels = [1.0, 1.0, -1.0, -1.0, 1.0]
    return datamat, lavels

#弱分类器分类函数
#参数:数据集 特性所在列 特性阈值 分类值为1或-1
def lowType(Data, x, num, t):
    res = ones((Data.shape[0], 1))
    if t == 'less':
        res[Data[ : ,x] <= num] = -1
    else:
        res[Data[ : ,x] > num] = -1
    return res

#训练一个低级分类器,从多个弱分类器中选出误差值最小的
def trainClassify(datas, lavel, D):
    Datamat = mat(datas)
    Lavels = mat(lavel).T
    m ,n = shape(Datamat)
    best = {}
    bestlavels = mat(ones((m, 1)))
    step = 10.0
    minerror = inf
    for i in range(n):
        minnum = Datamat[ : , i].min()
        maxnum = Datamat[ : , i].max()
        times = (maxnum - minnum) / step
        for j in range(-1, int(step) + 1):
            number = minnum + j * times
            for k in ['less', 'large']:
                r = lowType(Datamat, i, number, k)
                error = mat(ones((m, 1)))
                error[r == Lavels] = 0
                weights = error.T * D
                print "特性行:%d 特性分类值:%f 特性值选择方式:%s 误差值%f"%                (i, number, k, weights)
                if weights < minerror:
                    minerror = weights
                    bestlavels = r.copy()
                    best['row'] = i
                    best['number'] = number
                    best['types'] = k
    return best, minerror, bestlavels

#adaboost训练器
def adaboostTrain(dataset, lavels, cycle = 40):
    adaboost = []
    m, n = shape(dataset)
    D = mat(ones((m, 1)) / m)
    lastlavels = zeros((m ,1))
    for i in range(cycle):
        temp, temperror, templavels = trainClassify(dataset, lavels, D)
        print "D:", D.T
        alpha = float(0.5 * log((1.0 - temperror) / max(temperror, 1e-16)))
        temp['alpha'] = alpha
        adaboost.append(temp)
        print "第%d次预测的结果:"%(i + 1), templavels.T
        e = multiply(-1 * alpha * mat(lavels).T, templavels)
        D = multiply(D, exp(e))
        D = D / D.sum()
        lastlavels += alpha * templavels
        print "高级分类器的结果:", lastlavels.T
        lasterror = multiply(sign(lastlavels) != mat(lavels).T, ones((m, 1)))
        errorRate = lasterror.sum() / m
        print "错误率为%f"%(errorRate)
        if errorRate == 0.0:
            break
    return adaboost

#分类预测,参数为测试数据和adaboost分类器
def adaboostClassify(testdata, adaboost):
    testmat = mat(testdata)
    m = shape(testmat)[0]
    classifylavels = zeros((m, 1))
    for i in range(len(adaboost)):
        templavels = lowType(testmat, adaboost[i]['row'],         adaboost[i]['number'], adaboost[i]['types'])
        classifylavels += adaboost[i]['alpha'] * templavels
        print classifylavels
    return sign(classifylavels)    

#数据加载函数
def loadDataSet(filename):
    featruenum = len(open(filename).readline().split('\t'))
    f = open(filename)
    data = []
    l = []
    for i in f.readlines():
        line = i.strip().split('\t')
        temp = []
        for arr in range(featruenum - 1):
            temp.append(float(line[arr]))
        data.append(temp)
        l.append(float(line[-1]))
    return mat(data), l











以上是关于机器学习day12 机器学习实战adaboost集成方法与重新进行疝马病的预测的主要内容,如果未能解决你的问题,请参考以下文章

机器学习实战笔记-利用AdaBoost元算法提高分类性能

机器学习实战笔记(Python实现)-06-AdaBoost

Java 机器学习库Smile实战AdaBoost

《机器学习实战第7章:利用AdaBoost元算法提高分类性能》

机器学习实战之 第七章 集成方法(随机森林和 AdaBoost)

机器学习——Boosting算法与Adaboost算法