AdaBoost
AdaBoost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器,然后把这些分类器集合起来,构成一个更强的最终分类器。
抛出问题:给定一些弱的分类器、一个训练集和一个测试集。要求利用训练集训练分类器,然后给测试集分类。我们该如何去做?
解决的方案有如下:
方案一:将每个分类器都试一下,挑出最好的那个。
方案二:先用一个分类器分类随机部分训练集数据,再用其他训练器分类随机分部分训练集数据,得到的结果进行取平均值或者多数投票获取最终结果。
方案三:先用一个分类器分类随机部分训练集数据,再用同样的训练器分类随机分部分训练集数据,得到的结果进行取平均值或者多数投票获取最终结果。
方案四:先用一个分类器分类,然后根据得出的结果做一些调整,再用其他分类器进行分类,循环往复。
方案五:先用一个分类器分类,然后根据得出的结果做一些调整,再用同一个分类器进行分类,循环往复。
以上的方案中,方案一自不用说,给定相对于此数据集弱的分类器,那肯定不会有好结果,而另外四种方案其实就是异质集成和同质集成的Bagging和Boost。 何为异质集成?就是在训练数据的时候使用不同的训练器如方案二和方案四,那么相反的同质集成就是方案三和五了,前两个为Bagging的做法后两个为AdaBoost的做法, 而本文提到的正是同质集成的AdaBoost,这个也是相对比较简单的做法。
以下为AdaBoost的伪代码:
通过观察流程图我们可以发现,这个AdaBoost算法似乎只能对二分类数据进行分类,因为它输出的强分类器是弱分类器的线性组合而这种二分类处理上似乎也只能规范到-1,1两种情况,而我们要处理的数据为26分类。 这就需要新的AdaBoost算法来解决这个问题。
通过对比发现多分类的AdaBoostM1在求解α(β)上更加简单,没有了指数运算这对于大数据集是一个福音,而且多数投票也是一个相对比较简单的做法。
接下来我将利用Matlab以CART作为弱分类器,letter-recognition作为数据集构建一个实例。
第一步:拿到数据集种类首先需要将数据集分成两块,第一块为训练集,第二块为测试集。本次实验采用留出法。
rate=0.7; %训练集比例
data=importdata('letter-recognition.data');
n=length(data.rowheaders);
trainX=data.data(1:n*rate,:);
trainY=data.rowheaders(1:n*rate);
testX=data.data(n*rate+1:end,:);
testY=data.rowheaders(n*rate+1:end);
第二步:搭建弱分类器模板,这里我们直接使用Matlab自带的函数fitctree来构建决策树。
Mdl=fitctree(trainX,trainY,'Weights',weight);
第三步:进行重复训练并获取各个阶段的分类器
time=50; %分类器个数
weight=ones(size(trainY)); %权重初始化
cistern=cell(1,time); %存放分类器的元胞组
for i=1:time
Mdl=fitctree(trainX,trainY,'Weights',weight); %训练分类器
result=predict(Mdl,trainX);%预测训练集上的结果
errorindex=find(strcmp(result,trainY)==0);%分类错误下标
correctindex=find(strcmp(result,trainY)==1);%分类正确下标
errorrate=sum(weight(errorindex)./length(weight));%计算错误率,由于weight数组在fitctree中为自动适应,没有归一所以现在需要归一。
cistern{i}=Mdl;
alpha=errorrate/(1-errorrate);%计算α(β)
weight(correctindex)=weight(correctindex)*alpha;%调整权重
end
第四步:进行测试集的测试。
answer=cell(length(testY),time);%存放每个分类器的结果
error=zeros(1,time);%存放每次组合的错误率
for i=1:time
answer(:,i)=predict(cistern{i},testX);
k=cell(size(testY));%存放每次组合最终结果
for j=1:length(testY) %求出对于第j个样本i个预测结果中频率最高的结果
table=tabulate(answer(j,1:i));
[~,idx] = max(cell2mat(table(:,2)));
k{j}=table{idx};
end
error(i)=length(find(strcmp(k,testY)==0))/length(testY);%求出测试集上每次组合最终结果的错误率
index=1:i;
fprintf('%d个分类器组合,错误率:%6.2f\n',i,error(i));
title('测试集分类错误率变化曲线');
plot(index,error(1:i));
hold on;
end
结果如下: