数据挖掘十大经典算法 <一> :Adaboost算法
来源:互联网 发布:天刀捏脸数据男五毒 编辑:程序博客网 时间:2024/06/04 19:36
研究在Schapire的大作中提到了一个Toy Game的例子,这里给出了一个类似的Matlab代码。
先上一段代码:
首先是程序需要产生一些随机的样本数据,然后分别调用其他的matlab函数实现分类结果输出。代码如下:
clear allclctr_n=200; %the population of the train sette_n=200; %the population of the test setweak_learner_n=20; %the population of the weak_learnertr_set=[1,5;2,3;3,2;4,6;4,7;5,9;6,5;6,7;8,5;8,8];te_se=[1,5;2,3;3,2;4,6;4,7;5,9;6,5;6,7;8,5;8,8];tr_labels=[2,2,1,1,2,2,1,2,1,1];te_labels=[2,2,1,1,2,2,1,2,1,1];figure;subplot(2,2,1);hold on;axis square;indices=tr_labels==1;plot(tr_set(indices,1),tr_set(indices,2),'b*');indices=~indices;plot(tr_set(indices,1),tr_set(indices,2),'r*');title('Training set');subplot(2,2,2);hold on;axis square;indices=te_labels==1;plot(te_set(indices,1),te_set(indices,2),'b*')3;indices=~indices;plot(te_set(indices,1),te_set(indices,2),'r*');title('Training set');% Training and testing error ratestr_error=zeros(1,weak_learner_n);te_error=zeros(1,weak_learner_n);for i=1:weak_learner_n adaboost_model=adaboost_tr(@threshold_tr,@threshold_te,tr_set,tr_labels,i); [L_tr,hits_tr]=adaboost_te(adaboost_model,@threshold_te,te_set,te_labels); tr_error(i)=(tr_n-hits_tr)/tr_n; [L_te,hits_te]=adaboost_te(adaboost_model,@threshold_te,te_set,te_labels); te_error(i)=(te_n-hits_te)/te_n;endsubplot(2,2,3);plot(1:weak_learner_n,tr_error);axis([1,weak_learner_n,0,1]);title('Training Error');xlabel('weak classifier number');ylabel('error rate');grid on;subplot(2,2,4);axis square;plot(1:weak_learner_n,te_error);axis([1,weak_learner_n,0,1]);title('Testing Error');xlabel('weak classifier number');ylabel('error rate');grid on;
这里需要另外分别撰写两个函数,其中一个为生成adaboost模型的训练函数,另外为测试测试样本的测试函数。代码如下:
function adaboost_model=adaboost_tr(tr_func_handle,te_func_handle,train_set,labels,no_of_hypothesis)% 训练函数adaboost_model = struct('weights',zeros(1,no_of_hypothesis),... 'parameters',[]); %cell(1,no_of_hypothesis));sample_n = size(train_set,1);samples_weight = ones(sample_n,1)/sample_n;for turn=1:no_of_hypothesis adaboost_model.parameters{turn} = tr_func_handle(train_set,samples_weight,labels); [L,hits,error_rate] = te_func_handle(adaboost_model.parameters{turn},... train_set,samples_weight,labels); if(error_rate==1) error_rate=1-eps; elseif(error_rate==0) error_rate=eps; end % The weight of the turn-th weak classifier adaboost_model.weights(turn) = log10((1-error_rate)/error_rate); C=likelihood2class(L); t_labeled=(C==labels); % true labeled samples % Importance of the true classified samples is decreased for the next weak classifier samples_weight(t_labeled) = samples_weight(t_labeled)*... ((error_rate)/(1-error_rate)); % Normalization samples_weight = samples_weight/sum(samples_weight);end% Normalizationadaboost_model.weights=adaboost_model.weights/sum(adaboost_model.weights);-------------function [L,hits]=adaboost_te(adaboost_model,te_func_handle,test_set,... true_labels)%测试函数hypothesis_n=length(adaboost_model.weights);sample_n=size(test_set,1);class_n=length(unique(true_labels));temp_L=zeros(sample_n,class_n,hypothesis_n);for i=1:hypothesis_n [temp_L(:,:,i),hits,error_rate]=te_func_handle(adaboost_model.parameters{i},... test_set,ones(sample_n,1),true_labels); temp_L(:,:,i)=temp_L(:,:,i)*adaboost_model.weights(i);endL=sum(temp_L,3);hits=sum(likelihood2class(L)==true_labels);— —— ——
其中上面函数由于体积太大,另外还需要分别撰写两个阈值函数和一个隶属分配函数。
function model=threshold_tr(train_set,sample_weights,labels)% 训练阈值函数model=struct('min_error',[],'min_error_thr',[],'pos_neg',[],'dim',[]);sample_n=size(train_set,1);min_error=sum(sample_weights);min_error_thr=0;pos_neg='pos';% for each dimensionfor dim=1:size(train_set,2) sorted=sort(train_set(:,dim),1,'ascend'); % for each interval in the specified dimension for i=1:(sample_n+1) if(i==1) thr=sorted(1)-0.5; elseif(i==sample_n+1) thr=sorted(sample_n)+0.5; else thr=(sorted(i-1)+sorted(i))/2; end ind1=train_set(:,dim)<thr; ind2=~ind1; tmp_err=sum(sample_weights((labels.*ind1)==2))+sum(sample_weights((labels.*ind2)==1)); if(tmp_err<min_error) min_error=tmp_err; min_error_thr=thr; pos_neg='pos'; model.dim=dim; end ind1=train_set(:,dim)<thr; ind2=~ind1; tmp_err=sum(sample_weights((labels.*ind1)==1))+sum(sample_weights((labels.*ind2)==2)); if(tmp_err<min_error) min_error=tmp_err; min_error_thr=thr; pos_neg='neg'; model.dim=dim; end endendmodel.min_error=min_error;model.min_error_thr=min_error_thr;model.pos_neg=pos_neg;function [L,hits,error_rate]=threshold_te(model,test_set,sample_weights,true_labels)% 测试阈值函数feat=test_set(:,model.dim);if(strcmp(model.pos_neg,'pos')) ind=(feat>model.min_error_thr)+1;else ind=(feat<model.min_error_thr)+1;endhits=sum(ind==true_labels);error_rate=sum(sample_weights(ind~=true_labels));L=zeros(length(feat),2);L(ind==1,1)=1;L(ind==2,2)=1;function classes=likelihood2class(likelihoods)% 隶属分配函数[sample_n,class_n] = size(likelihoods);maxs = (likelihoods==repmat(max(likelihoods,[],2),[1,class_n]));classes=zeros(sample_n,1);for i=1:sample_n classes(i) = find(maxs(i,:),1);end
很早就想过通过组合弱分类器来实现一个强分类器的问题。当学习到线性分类器以及著名的决策树之类分类器后,很容易联想到高中时代线性规划里面对不少区域的划分。要是能够找到一种方法,组合这些简单的直线方程,不就可以实现“山寨诸葛亮”的理想?
实际上,在Kearns和Valiant在1989年大作中指出了这种算法的可行性。而后,Freund在1990年以及他和Schapire在1994-1996年提出了boosting整个算法思路,似乎这种算法走到了实际应用的开端。然而直到AdaBoost被viola在其人脸识别系统中运用(2001Viola和Jones),这种方法才彻底开始暴火。
Adaboost实际具体解决了两个问题:
1.怎么处理训练样本?
在AdaBoost中,每个样本都被赋予一个权重。如果 某个样本没有被正确分类,它的权重就会被提高, 反之则降低。这样, AdaBoost方法将注意力更多 地放在“难分”的样本上。
2.怎么合并若分类器成为一个强分类器?
强分类器表示为若干弱分类器的线性加权和形式, 准确率越高的弱学习机权重越高。
好了。
以下参考:http://stblog.baidu-tech.com/?p=19一、Boosting算法的发展历史
Boosting算法是一种把若干个分类器整合为一个分类器的方法,在boosting算法产生之前,还出现过两种比较重要的将多个分类器整合为一个分类器的方法,即boostrapping方法和bagging方法。我们先简要介绍一下bootstrapping方法和bagging方法。
1)bootstrapping方法的主要过程
主要步骤:
i)重复地从一个样本集合D中采样n个样本
ii)针对每次采样的子样本集,进行统计学习,获得假设Hi
iii)将若干个假设进行组合,形成最终的假设Hfinal
iv)将最终的假设用于具体的分类任务
2)bagging方法的主要过程
主要思路:
i)训练分类器
从整体样本集合中,抽样n* < N个样本 针对抽样的集合训练分类器Ci
ii)分类器进行投票,最终的结果是分类器投票的优胜结果
但是,上述这两种方法,都只是将分类器进行简单的组合,实际上,并没有发挥出分类器组合的威力来。直到1989年,Yoav Freund与 Robert Schapire提出了一种可行的将弱分类器组合为强分类器的方法。并由此而获得了2003年的哥德尔奖(Godel price)。
Schapire还提出了一种早期的boosting算法,其主要过程如下:
i)从样本整体集合D中,不放回的随机抽样n1 < n 个样本,得到集合 D1
训练弱分类器C1
ii)从样本整体集合D中,抽取 n2 < n 个样本,其中合并进一半被 C1 分类错误的样本。得到样本集合 D2
训练弱分类器C2
iii)抽取D样本集合中,C1 和 C2 分类不一致样本,组成D3
训练弱分类器C3
iv)用三个分类器做投票,得到最后分类结果
到了1995年,Freund and schapire提出了现在的adaboost算法,其主要框架可以描述为:
i)循环迭代多次
更新样本分布
寻找当前分布下的最优弱分类器
计算弱分类器误差率
ii)聚合多次训练的弱分类器
在下图中可以看到完整的adaboost算法:
图1.1 adaboost算法过程
现在,boost算法有了很大的发展,出现了很多的其他boost算法,例如:logitboost算法,gentleboost算法等等。在这次报告中,我们将着重介绍adaboost算法的过程和特性。
二、Adaboost算法及分析
从图1.1中,我们可以看到adaboost的一个详细的算法过程。Adaboost是一种比较有特点的算法,可以总结如下:
1)每次迭代改变的是样本的分布,而不是重复采样(re weight)
2)样本分布的改变取决于样本是否被正确分类
总是分类正确的样本权值低
总是分类错误的样本权值高(通常是边界附近的样本)
3)最终的结果是弱分类器的加权组合
权值表示该弱分类器的性能
简单来说,Adaboost有很多优点:
1)adaboost是一种有很高精度的分类器
2)可以使用各种方法构建子分类器,adaboost算法提供的是框架
3)当使用简单分类器时,计算出的结果是可以理解的。而且弱分类器构造极其简单
4)简单,不用做特征筛选
5)不用担心overfitting!
总之:adaboost是简单,有效。
下面我们举一个简单的例子来看看adaboost的实现过程:
图中,“+”和“-”分别表示两种类别,在这个过程中,我们使用水平或者垂直的直线作为分类器,来进行分类。
第一步:
根据分类的正确率,得到一个新的样本分布D2,一个子分类器h1
其中划圈的样本表示被分错的。在右边的途中,比较大的“+”表示对该样本做了加权。
第二步:
根据分类的正确率,得到一个新的样本分布D3,一个子分类器h2
第三步:
得到一个子分类器h3
整合所有子分类器:
因此可以得到整合的结果,从结果中看,及时简单的分类器,组合起来也能获得很好的分类效果,在例子中所有的。
Adaboost算法的某些特性是非常好的,在我们的报告中,主要介绍adaboost的两个特性。一是训练的错误率上界,随着迭代次数的增加,会逐渐下降;二是adaboost算法即使训练次数很多,也不会出现过拟合的问题。
下面主要通过证明过程和图表来描述这两个特性:
1)错误率上界下降的特性
从而可以看出,随着迭代次数的增加,实际上错误率上界在下降。
2)不会出现过拟合现象
通常,过拟合现象指的是下图描述的这种现象,即随着模型训练误差的下降,实际上,模型的泛化误差(测试误差)在上升。横轴表示迭代的次数,纵轴表示训练误差的值。
而实际上,并没有观察到adaboost算法出现这样的情况,即当训练误差小到一定程度以后,继续训练,返回误差仍然不会增加。
对这种现象的解释,要借助margin的概念,其中margin表示如下:
通过引入margin的概念,我们可以观察到下图所出现的现象:
从图上左边的子图可以看到,随着训练次数的增加,test的误差率并没有升高,同时对应着右边的子图可以看到,随着训练次数的增加,margin一直在增加。这就是说,在训练误差下降到一定程度以后,更多的训练,会增加分类器的分类margin,这个过程也能够防止测试误差的上升。
三、多分类adaboost
在日常任务中,我们通常需要去解决多分类的问题。而前面的介绍中,adaboost算法只能适用于二分类的情况。因此,在这一小节中,我们着重介绍如何将adaboost算法调整到适合处理多分类任务的方法。
目前有三种比较常用的将二分类adaboost方法。
1、adaboost M1方法
主要思路: adaboost组合的若干个弱分类器本身就是多分类的分类器。
在训练的时候,样本权重空间的计算方法,仍然为:
在解码的时候,选择一个最有可能的分类
2、adaboost MH方法
主要思路: 组合的弱分类器仍然是二分类的分类器,将分类label和分类样例组合,生成N个样本,在这个新的样本空间上训练分类器。
可以用下图来表示其原理:
3、对多分类输出进行二进制编码
主要思路:对N个label进行二进制编码,例如用m位二进制数表示一个label。然后训练m个二分类分类器,在解码时生成m位的二进制数。从而对应到一个label上。
四、总结
最后,我们可以总结下adaboost算法的一些实际可以使用的场景:
1)用于二分类或多分类的应用场景
2)用于做分类任务的baseline
无脑化,简单,不会overfitting,不用调分类器
3)用于特征选择(feature selection)
4)Boosting框架用于对badcase的修正
只需要增加新的分类器,不需要变动原有分类器
由于adaboost算法是一种实现简单,应用也很简单的算法。Adaboost算法通过组合弱分类器而得到强分类器,同时具有分类错误率上界随着训练增加而稳定下降,不会过拟合等的性质,应该说是一种很适合于在各种分类场景下应用的算法。
待续。。。
- 数据挖掘十大经典算法 <一> :Adaboost算法
- 数据挖掘十大经典算法(7) AdaBoost
- 数据挖掘十大经典算法(7) AdaBoost
- 数据挖掘十大经典算法(7) AdaBoost
- 数据挖掘十大经典算法之AdaBoost
- 数据挖掘十大经典算法(7) AdaBoost
- 数据挖掘十大经典算法(7) AdaBoost
- 数据挖掘十大经典算法(7) AdaBoost
- 数据挖掘十大经典算法(7) AdaBoost
- 数据挖掘十大经典算法(7) AdaBoost
- 数据挖掘十大经典算法(七) AdaBoost
- 数据挖掘十大经典算法(7) AdaBoost
- 数据挖掘十大经典算法学习之Adaboost自适应增强学习算法
- 数据挖掘十大经典算法学习之Adaboost自适应增强学习算法
- 数据挖掘十大算法--浅谈Adaboost算法
- 数据挖掘十大经典算法(一)C4.5
- 自学数据挖掘十大算法之AdaBoost
- 数据挖掘十大算法翻译——7AdaBoost
- Android - 常见错误的解决方法
- 北京实习总结——记住牛人那些话
- Android - 主要的UI元素
- LISP 8.6 生成展开式
- Qt-4.7.2及QtEmbedded-4.7.2 在ubuntu 11.10下的安装
- 数据挖掘十大经典算法 <一> :Adaboost算法
- Qt中创建菜单和工具栏的一点总结
- Objective-c 和 Mac操作系统
- linux 发无线 软AP hostapd+dnsmasq
- poj 2485 Highways
- 红外遥控解码驱动代码
- Spring MVC 教程,快速入门,深入分析
- SEO学习(五)——关键词的研究
- Ubuntu12.04下使用doxygen生成API文档