《统计学习方法》 Adaboost算法 Python实现

来源:互联网 发布:excel账单数据分列 编辑:程序博客网 时间:2024/06/06 23:44

 最近在接触Adaboost算法,在实现的时候,有一些问题,值得注意。
 本文参考《统计学习方法》这个书本P140例子8.13实现的。
 首先先列算法。

引用《统计学习方法》P138 8.1.2算法
输入:训练数据集T ={(x1,y1),(x2,y2),...,(xN,yN)},其中xiXRnyiY={1,+1};弱学习算法。
输出:最终分类器G(x)
(1),初始化训练数据的权值分布

D1=(w11,...,w1i,...,w1N)w1i=1/Ni=1,2,...,N

(2)对m=1, 2,…, M
 (a)使用具有权值分布Dm的训练数据集学习,得到基本分类器
Gm(x):X{1,+1}

 (b)计算Gm(x)在训练数据集上的分类误差率
 (c)计算Gm(x)的系数
am=12log1emem

这里的对数是自然对数。
 (d)更新训练数据集的权值分布
Dm+1=(wm+1,1,,wm+1,i,,wm+1,N)

wm+1,i=wmiZmexp(amyiGm(xi))

这里,Zm是规范化因子
它使Dm+1成为一个概率分布。
(3)构建基本分类器的线性组合
f(x)=m=1MamGm(x)

得到最终分类器
G(x)=sign(f(x))=sign(m=1MamGm(x))

 刚开始也一直在思索如何找出那个书上的那个弱分类器,后来参考了一下别人的博文,这个叫做阈值分类器,提到阈值分类器也只能适用于单特征的。
 这里有两个问题。
 Adaboost的权值分布w是干嘛用的?w是权值用来计算em用的,我们的目标是找出最小的误差率。
 Adaboost算法什么时候停止循环?这里我定义了一个误差率小于0.2即停止。
 以下贴个代码,就是对应书上的P140 8.1.3例子。
 这里有个坑要注意一下,就是这里的分类器,有正负的分类器,可以看下P141页,G2分类器和G3分类器,G2是x<8.5预测为1,G3是x>5.5预测为1,这里要注意一下,写代码要考虑到这两个正负的最小误差率。

import numpy as npclass Adaboost:    def train(self, dataSet, labels):   #训练方法        weights = np.ones(len(dataSet)) * (1.0 / len(dataSet)) #初始化权值        # flag = True #第一个e的赋值开关        self.vList = [] #用来存储阈值,因为我们用的是阈值分类器        self.aList = [] #存储alpha的,没啥用        self.classify = []  #分类器选哪个,因为有正分类器,负分类器        min_e = 1        while min_e > 0.2:            v = min(dataSet) + 0.5  #设置初始值            flag = True #第一个e的赋值开关            classifyFlag = True            while v <= max(dataSet):                e = 0                for i, row in enumerate(dataSet):   #遍历数据集,计算误差率                    value = 1 if labels[i] * self.Gm(row, v) < 0 else 0                    e += weights[i] * value                if flag == True or e < min_e:   #寻找最小的误差率的阈值                    min_e = e                    min_v = v                    flag = False                    classifyFlag = True                e = 0                for i, row in enumerate(dataSet):   #遍历数据集,计算误差率,但这次是负分类器                    value = 1 if labels[i] * self.Gm(row, v, False) < 0 else 0                    e += weights[i] * value                if e < min_e:                    min_e = e                    min_v = v                    classifyFlag = False                v += 0.5    #步长            self.vList.append(min_v)    #将最小误差的阈值加入进去            self.classify.append(classifyFlag)  #正负分类器的区别            a = 1 / float(2) * np.log((1-min_e) / min_e)    #计算alpha            zm = 0            for i in range(len(dataSet)):   #计算书中的zm                zm += weights[i] * np.exp(-a * labels[i] * self.Gm(dataSet[i], min_v))  #            sum = np.sum(weights)            for i in range(len(dataSet)):                weights[i] =  weights[i] / float(zm) * np.exp(-a * labels[i] * self.Gm(dataSet[i], min_v))  #更新权重            self.aList.append(a)            print(min_e)        #print(self.aList)        print(self.vList)        print(self.classify)    def Gm(self, x, v, flag = True):#简单的阈值分类器        if (flag == True):            return -1 if x >= v else 1        else:            return 1 if x >= v else -1    def predict(self, x):   #预测方法        sum = 0        for i in range(len(self.vList)):    #书上最终分类器的代码ii           sum += self.aList[i] * self.Gm(x, self.vList[i], self.classify[i])        return 1 if sum > 0 else -1if __name__ == '__main__':    print("Test")    dataSet = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]    #数据集    labels = [1, 1, 1, -1, -1, -1, 1, 1, 1, -1] #标签    adaboost = Adaboost()    adaboost.train(dataSet, labels)    for i in range(10, 20):        print(adaboost.predict(i))
阅读全文
0 0
原创粉丝点击