各种Adaboost variants的比较以及不均衡问题

本文详细介绍了Adaboost及其多种变种算法,包括DiscreteAdaboost、RealAdaboost、GentleAdaboost等,并探讨了它们在处理数据不平衡问题上的表现。

一直以来,Adaboost都是我比较喜欢的模式分类方法,工作当中用的也比较多,Adaboost的算法思想决定了其特别适合于机器视觉中的目标检测任务,即简单的易于区分的只用很少的弱分类器就可以区分,较难的则使用更多的弱分类器来区分。本篇博客简要介绍Adaboost及其变种(variants),重点放在各种variants的实现及差别(尤其是在数据不平衡情况下的差别),以便在工作中针对不同问题灵活选取Adaboost 的type。这里主要介绍Discrete Adaboost, Real Adaboost, Gentle Adaboost, Modest  Adaboost, Parameterized Adaboost 及Penalized Adaboost。

关于Adaboost,首先借参考文献中的一幅图,整体了解其发展


各种Adaboost variants本质上是相同的,只是在弱分类器的输出及样本权重更新有所差别,本博客这里只选取decision stump作为weak classifier。                                

Discrete Adaboost  

Discrete Adaboost是最简单的Adaboost,其算法流程如下图所示


Discrete Adaboost弱分类器的输出为+1, -1,为了各种Variants统一,定义decision stump                      
% stump is a structure with the flowing field
%   .fidx                    feature index 
%   .thresh                  local thrshold of the stump
%   .parity                  predicting parity (+1: > threshold is positive, -1: > threshold is negative)
%   .posProb                 probability for positive
%   .negProb                 probability for neagtive
%   .error                   local weighted error
这里定义了decision stump的输出概率,对于Discrete Adaboost,每个decision stump(weak classifier)对应的概率要么是+1,要么是-1,而后面要讲的Real Adaboost, posProb 与negProb 就是具体的实数,可以用于分类器分类准确的置信度。decision stump可以采用Exhaustive Search的方法选择最佳的threshold,再根据符号指示器parity就可以用decision stump进行预测。                                                                                                                                                                                                                                                  
  • Real Adaboost
Real Adaboost可以说是Adaboost家族的一般形式(实现与此有所差别)

Real Adaboost的弱分类器输出不在是+1,-1两种形式,而是一个实数,这个实数可以作为Adaboost判别的置信度。那么,这个实数到底是如何计算的呢?就Decision stump而言,类似于Discrete Adaboost的方法,每一轮都可以找到一个最优的decision stump, 这个stump的thresh将整个trainingData划分两部分S1与S2,一部分(假定S1)预测为positive,另一部分(S2)预测为negative,显然根据trainData划分S1不会完完全全都是正样本(会有少许的负样本,但绝大部分还是正样本),那么这个正样本与负样本的
加权数量比例就可以作为Decision Stump的概率输出,S2也类似。                                                                                                                                                                                                      
  • Gentle Adaboost
Gentle Adaboost是号称鲁棒性,实际效果最好的Adaboost,其算法流程如下图所示(实现有所差别)
Gentle Adaboost与Real Adaboost就是在弱分类器概率输出上有所差别,其余完全一样。同Real Adaboost类似,每一轮找到一个最优的decision stump, 这个stump的thresh将整个trainingData划分两部分S1与S2,一部分(假定S1)预测为positive,另一部分(S2)预测为negative,此时正样本的概率输出是正负样本的加权只差与正负样本的加权之和的比例,S2与此类似。
  • Modest Adaboost
Modest Adaboost 与Real Adaboost的区别也是在弱分类器的输出,其算法流程如下

Modest Adaboost在计算弱分类器的输出时增加了样本的反向加权项或者倒数加权项。实际情况的Modest Adaboost好像不是特别好,特别是样本不均衡的条件下,Modest Adaboost 很差。
  • Parameterized Adaboost
Parameterized Adaboost算法流程如下图所示

与Real Adaboost相比,Parameterized Adaboost在样本权重更新上增加了一个惩罚项,其作用就是使得margin接近于0的样本得到更多的更新机会,当alpha为0时,Parameterized Adaboost就是Real Adaboost。
  • MarginPruning Adaboost
MarginPruning Adaboost是从margin的角度来改变原始Adaboost,其设计的目的就是减少noise的影响

MarginPruning Adaboost在权重更新时,如果发现当前样本很有可能是noise,则将重置其样本权重,而不是增加其样本权重让其在下一轮分正确。
  • Penalized Adaboost
Penalized Adaboost是在MarginPruning Adaboost的基础上改进的

Penalized Adaboos可以减少margin很小的样本的分类错误概率,具有更小的泛化误差。
  • Cost-Generalized AdaBoost
严格意义上Cost-Generalized Adaboost不是某一种Adaboost,而是一类Adaboost,这类Adaboost可以解决样本不均衡的问题。在图像目标检测过程中,正样本相较于负样本往往是很少的,大千世界我们看到各种各样的自然景色,可是往往我们关心的只是那么几类,对于这种样本不平均的分类问题,显然上述的各种Adaboost的variants是不适合的,因为上述的Adaboost variants的目标是只是最小化分类误差,正负样本的重要性是同等的,此时就需要一种非对称(Asymmetric)的 Adaboost的或者说不均衡的Adaboost。
很多文献提出了文献各种样本不均衡的Adaboost,像AdaCost,AdaC1, AdaC2,AdaC3等等

 文献Shedding Light on the Asymmetric Learning Capability of AdaBoos理论上t阐明了Adaboost本身就是一种样本不均衡的分类器,只要修改样本的初始权重就可以使得正样本完全分正确(本人很喜欢这样的发现,前面的不均衡Adaboost要增加惩罚项神马的不知道理论上会不会很好疑问),一开始我也对这个发现持怀疑态度,就从最基本的Discrete Adaboost出发来验证一下
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Asymmetric Adaboost train demo(Cost-Sensitive AdaBoost algorithms)
clc; clear all;
close all;

%% Make training data of two classes "red" and "blue"
% with 2 features for each sample (the position  x and y).
Nb = 1500; Nr = 100;
angle = rand(Nb,1)*2*pi; l = rand(Nb,1)*40+30; blue = [sin(angle).*l cos(angle).*l];
angle = rand(Nr,1)*2*pi; l = rand(Nr,1)*40;    red  = [sin(angle).*l cos(angle).*l];

% All the training data
trainData = [blue;red];
trainLabel(1:Nb) = -1; trainLabel(Nb+1:Nb+Nr) = 1;
trainLabel = trainLabel(:);

% Show the data
figure;
plot(blue(:,1), blue(:,2), 'b.');  hold on;  plot(red(:,1), red(:,2), 'r.');
grid on; legend('Negative', 'Positive'); title('Training Data');

%% Cost-Generalized AdaBoost
Cp = 0.5;   Cn = 0.3;       
weight_p = ones(Nr, 1)/Nr;
weight_n = ones(Nb, 1)/Nb;
weight   = [Cn/(Cp+Cn)*weight_n; Cp/(Cp+Cn)*weight_p]; 
weight   = weight/sum(weight);

itrNum = 100;
models = []; casErr = []; casErrPos = []; casErrNeg = [];
predictedLabelCascade = zeros(size(trainLabel));
for k = 1 : itrNum
     % train a decision stump(weak classifier)
     stump = DecisionStumpTrain(trainData, trainLabel, weight, 'Discrete');
     predictedLabel = DecisionStumpPredict(stump, trainData);
     
     % weak classifier influence on total result is based on the current
     % classification error
     alpha = 0.5 * log((1-stump.error)/max(stump.error,eps)); 
     
     % update samples weights
     weight = weight .* exp(-alpha.*trainLabel.*predictedLabel);
     weight = weight / sum(weight);
     
     % calculate the current error of the cascade of weak classifiers
     predictedLabelCascade = predictedLabelCascade + predictedLabel*alpha;
     casPrecdict           = sign(predictedLabelCascade);
     casErr                = [casErr, sum(casPrecdict~=trainLabel) / (Nb+Nr)];
     casErrPos             = [casErrPos, sum((casPrecdict~=trainLabel).*(trainLabel==1)) / Nr];
     casErrNeg             = [casErrNeg, sum((casPrecdict~=trainLabel).*(trainLabel==-1)) / Nb];
   
     model.error = casErr(end);
     model.stump = stump;
     model.alpha = alpha;
     models = [models; model];
     if(model.error == 0); break; end
end

% figure out the cascade training error
figure; 
plot(casErr, 'r'); grid on; hold on; 
plot(casErrPos, 'g');  plot(casErrNeg, 'b');
legend('Total Error', 'Positive Error', 'Negative Error');

figure;
plot(blue(:,1), blue(:,2), 'b.'); grid on; hold on;  
plot(red(:,1), red(:,2), 'r.');
errIdx = find(casPrecdict ~= trainLabel);
plot(trainData(errIdx, 1), trainData(errIdx, 2), 'sm');
title(['TErr = ', num2str(sum(casPrecdict ~= trainLabel)), ...
       ', FN = ', num2str(sum((casPrecdict ~= trainLabel).*(trainLabel==1))), ...
       ', FP = ', num2str(sum((casPrecdict ~= trainLabel).*(trainLabel==-1)))]);
随机生成1500个负样本核100个正样本,设置正样本类别权重Cp=0.5,负样本类别权重Cn=0.3,结果如下:

发现对训练集总的分错的个数是142个,其中false negative只有2个羡慕。如果设置Cp = 0.5;   Cn = 0.1; 你会惊奇的发现,虽然总的分类错误个数增加了,但是FN居然为0(很好哦)。
由此一来,我们只需要修改正负样本的初始权重,加上正负样本类别的因子,上面7个Adaboost variants都可以解决样本不均衡问题了吧?(实际结果是不完全是)
  • 实验结果
为了验证7中Adaboost variants的泛化性能,我们测试了一组数据Nb = 400; Nr = 400;正负样本一样多),结果如下

取Nb = 400; Nr = 200,结果如下

发现Modest Adaboost效果好差。
同样的取Nb = 400; Nr = 200,改变样本的初始权重及类别因子
% initialize weight of samples
if 1   
    % Cost-Generalized AdaBoost
    Cp = 0.5;   Cn = 0.2;  
    weight = ones(size(trainLabel));
    weight(trainLabel==1)  = (1/sum(trainLabel==1)) * (Cp/(Cp+Cn));
    weight(trainLabel==-1) = (1/sum(trainLabel==-1)) * (Cn/(Cp+Cn));
else
    weight = ones(size(trainLabel));
    weight = weight / sum(weight);
end
结果如下

结果发现Discrete Adaboost, Real Adaboost及Gentle Adaboost加上Cost-Sensitive AdaBoost algorithms策略对样本不均衡的效果还是不错的,其余的就不好保证了。

参考文献:

2012 Ferreira Figueiredo Boosting Algorithms A Review of Methods Theory and Applications

2015 Analysis of Generalization Ability for Different AdaBoost Variants Based on Classification and Regression Trees

2015 Penalized AdaBoost Improving the Generalization Error ofGentle AdaBoost through a Margin Distribution

2015 Shedding Light on the Asymmetric Learning Capability of AdaBoost

2015 Revisiting AdaBoost for Cost-Sensitive Classification(1)

2015 Revisiting AdaBoost for Cost-Sensitive Classification(2)

关于Real_AdaBoost算法的分析与改进

评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值