基于Adaboost实现鸢尾花数据集分类
寫在之前
提交內容分為兩大部分:
一為Adaboost算法實現,代碼在文件夾《算法實現》中,《提升方法筆記》為個人學習筆記。
二為基于Adaboost模型實現鳶尾花數據集分類,代碼在《AdaBoost_iris》中。
注釋:
·弱分類器只是簡單的閾值判斷的方法,由于鳶尾花數據集線性可分,故分類準確率非常高
·為了便于理解,代碼實現了基于兩個特征的分類,并做了可視化
·作業中要求基本都已實現,運行結果在《基于Adaboost的鳶尾花分類》中
·為了便于調試,需要按節運行。
·函數注釋寫的已經非常清晰,可以運行help 'function name’查看函數使用說明,參考內容寫在了兩個文檔的末尾“參考”中。
一算法思想:
Adaboost是一種迭代算法,其核心思想是針對同一個訓練集訓練不同的分類器(弱分類器),然后把這些弱分類器集合起來,構成一個更強的最終分類器(強分類器)。(多個專家加權表決)。是一種重要的集成學習技術,能夠將預測精度僅比隨機猜度略高的弱學習器增強為預測精度高的強學習器。
1.樣本權值:
Adaboost采用了變樣本權值的方式進行學習,在每一次進行弱分類器進行學習時,首先將樣本的權值分布改變。改變的依據比較容易理解,即前一個弱分類器錯誤分類的樣本理應作為下一步需特別關注的對象,我們希望盡可能將他分對。那么怎樣才能將這種“特別關注”量化呢?我理解Adaboost算法改變樣本權值的做法類似于設置了一種“獎勵機制”,暫且將其命名為“餅干機制”,如果上一個分錯的樣本,在此次樣本中分對了,我們將給這次的弱分類器更多的“餅干”,(事實上Adaboost算法是一種“懲罰機制”,或者“損失機制”,期望讓分類誤差率更小,但本質上是一致的)那么問題落腳到了如何合理設計一個函數關系,讓“餅干數”與其表現呈現一種正相關關系。Adaboost算法首先初始化時,將所有樣本設置為等權重,并且滿足權重和為1。(我理解這里的操作是為了之后每次迭代時,都保證權重之和是1,這樣讓分類誤差率能夠相互比較,否則,可能分類誤差率為1.1和2.2可能并不能說明前者優于后者)。借助式1
可見,如果分類正確權值 下一步將會被壓縮,( 是大于0.5的,因為弱分類器的緣故),分類錯誤下一步 將會被放大如此便實現了樣本數據的權值分布。
2.弱分類器權值:
關于舉手表決,最為樸素的思想是,誰可信度更高,誰理應擁有更高的發言權。那么可信度這怎么來量化呢?由于我們在之前一步將分類誤差率量化成[0,1]之間的數,所以我們可以依靠分類誤差率來評判哪個弱分類器更為可靠。
二算法描述:
三算法實現:
1.隨機生成訓練樣本數據以及label,為了可視化方便起見,隨機生成的樣本具有兩個特征。如圖3-1。
2.對于每一維度特征,都采用閾值遍歷的方式進行弱分類器判斷,直到滿足要求退出訓練過程。(達到迭代次數或者訓練誤差率小于設定值)將訓練中的閾值可視化如圖3-2。
3.利用最終得到的分類器,得到估計的label與實際的label進行比較,計算測試集上的準確率如圖3-3。
四 思考:
·明明是同一個數據集,并且采用的是遍歷閾值的方法,為什么會得到不同的最佳閾值?
由于評價指標改變了,即樣本數據的權值分布改變,之前分類錯的樣本權值變大,如果要想將該樣本點分對,則需改變最佳閾值。
參考:
Adaboost入門教程——最通俗易懂的原理介紹(圖文實例)
https://blog.csdn.net/px_528/article/details/72963977
統計學習方法–提升樹模型(Boosting Tree)與梯度提升樹(GBDT)
https://www.cnblogs.com/daguankele/p/6557328.html
代碼
%% 樣本準備 clc;close;clear; % 生成數據與label --- 作圖顯示樣本數據 [data, label] = Data_set(100,2); figure(1);hold on;draw(data,label);title('訓練樣本'); %% 訓練 figure(2); [weakClassifier,strongClassifierLabel,m]=train(data,label,1000); draw(data,strongClassifierLabel);hold on;title('預測數據和相應的分割線'); %% 測試 [Label] = test(weakClassifier,data,label,m);function [data, label] = Data_set(m,n) % 樣本數據以及label生成 % 參數說明: % m:樣本數 % n:特征數 % lowT:根節點1 % highT:葉子節點數目% 參數缺省設置----及錯誤檢查----樣本應少于總樣本否則返回空 % if((m*n)>highT^2) % return; % end % 按照樣本產生數據 global lowT;lowT = 0; global highT; highT = 300; data = zeros(m,n); for i = 1:m data(i,:) = randi([lowT, highT],1,n);% randi([50,100],5) 返回一個由介于 50 和 100(包括二者)之間的隨機整數組成的 5×5 矩陣。 end% 分類label ∈{+1,-1} label = 2*randi([0, 1],m,1)-1;% 隨機整數endfunction draw(data,label) % 作圖 global lowT;global highT; plot(data(label==1,1),data(label==1,2),'go','LineWidth',3,'MarkerSize',4); plot(data(label==-1,1),data(label==-1,2),'ro','LineWidth',3,'MarkerSize',4); xlabel('x');ylabel('y');axis([lowT highT lowT highT]);endfunction drawline(dimemsion,threshVal,step) % 做出分割線;以及 global lowT;global highT;% X坐標 if(dimemsion==1)x=threshVal*ones(1,step+1);y=lowT:(highT-lowT)/step:highT;plot(x,y,'m:','lineWidth',2);hold on; end% Y坐標 if(dimemsion==2)y=threshVal*ones(1,step+1);x=lowT:(highT-lowT)/step:highT;plot(x,y,'m:','lineWidth',2);hold on; endendfunction [bestWeakClassifier,minEm,bestLabel]=select(data,label,D) % 函數功能說明: % _找到一弱分類器,使得分類誤差率足夠小,此分類器工作機制為硬閾值判斷; % _此弱分類器是針對某一個特征進行閾值判斷 % _分類誤差率是考慮被分類錯誤的樣本,使其對應權值相加 % % input: % D:為權值分布,反映了上一次弱分類器的分類情況 % bestWeakClassifier:找到的最佳閾值和最佳特征 % minEm:最小(弱)分類誤差率 % bestLabel:最佳弱分類時,所進行的估計[m,n] = size(data); step = m; % 閾值遍歷時需要設置步長,此處設置一個與數據樣本數相關的步長 bestWeakClassifier = []; % 最佳弱分類器 bestLabel = zeros(m,1); % 最佳的估計標簽 minEm = inf; % 最小誤差,初始化為無窮大 found=0; % This is for draw the split line(threshold) of every loopfor i=1:n % 按照不同特征作為分類依據進行分類minvalue = min(data(:,i));maxvalue = max(data(:,i));stepValue = (maxvalue-minvalue)/step; % 遍歷時的步長% 遍歷所有的數據取值for j = 0 : step % 閾值搜索的范圍為[minvalue,maxvalue]for exchange = -1:2:1 % 閾值判斷邏輯是否調換 threshval = minvalue + stepValue*j;WeakLabel = weakClassifier(data,i,threshval,exchange);% 錯誤數據為1,正確數據為0 || 計算em = Σw(誤分類樣本)errData = ones(m,1);errData(label == WeakLabel)=0;% 通過將D和勘誤相乘得到加權誤差em =D'*errData;% em = Σw(誤分類樣本):em:分類誤差率:分類錯誤的樣本的權值求和% 找到分類誤差率最小的閾值(分類器)if (em<minEm) % 記錄分類誤差最小的分類器基于的判斷特征+相應閾值+最小的誤差found=1;dimemsion = i;thresh_temp = threshval;minEm = em;bestLabel = WeakLabel;bestWeakClassifier={'dimension' i;'thresh' threshval;'exchange' exchange};endendend end % 一圈畫分割線(閾值) if (found ==1)drawline(dimemsion,thresh_temp,step);found = 0; endendfunction[Label] = test(weakClassifier,testData,testLabel,m) % 完成對測試集的測試num = size(testData,1); Label = []; for n = 1:numy = 0;for i = 0:m-1dimension = cell2mat(weakClassifier(i*4+1,2));thresh = cell2mat(weakClassifier(i*4+2,2));exchange = cell2mat(weakClassifier(i*4+3,2));alpha = cell2mat(weakClassifier(i*4+4,2));% 閾值邏輯判斷if(testData(n,dimension)>thresh)labell = 1;elselabell = -1;endlabell = labell * exchange;y = y + alpha * labell;endy = sign(y);Label = [Label;y]; end acc = sum(Label==testLabel)/size(testLabel,1); fprintf('在測試集上,得到的準確率為%f\n',acc); endfunction [weakClassifier,strongClassifier,i] = train(data,label,numIteration) % 參數及變量說明: % % input: % data:訓練樣本數據 % label:類別∈{+1,-1} % numIteration:迭代次數 % % output: % weakClassifier:一系列弱分類器 % err:錯誤分類率 % strongClassifier:強分類器(弱分類器的線性組合)得到的結果 % % % variable: % D:權值分布,初始化時為等權重(保證D始終是一個概率分布) % alpha:基本分類器的系數 % bestWeakClassifier:{'dimension';'thresh';'alpha'}m = size(data,1); weakClassifier = {}; D = ones(m,1)/m; % 初始化為等權重 combinedWeakClassifier = zeros(m,1);for i = 1:numIteration[bestWeakClassifier,minErr,bestLabel]=select(data,label,D);alpha= log((1-minErr)/minErr)/2;% 本次分類器對應的權重,為標量bestWeakClassifier(4,:) = {'alpha' alpha};% 存儲弱分類器參數weakClassifier=[weakClassifier;bestWeakClassifier];% 重新計算DD = D.*exp(-alpha*label.*bestLabel);D = D/sum(D);% 做歸一化處理% 弱分類器舉手表決(加權求和)combinedWeakClassifier = combinedWeakClassifier+alpha*bestLabel;% 強分類器strongClassifier = sign(combinedWeakClassifier);[~,err]=symerr(label,strongClassifier);% [number,ratio] = symerr(x,y)比較x和y。輸出ratio等于錯誤率。if(err <= 0.0001)break;end end fprintf('訓練集上準確率為:%f\n',1-err); end function [WeakLabel] = weakClassifier(data,dimension, threshval,exchange) % 函數功能:實現弱分類器(弱分類器) % input: % data:訓練樣本 % dimension:數據特征 % threshold:閾值,分類依據 % exchange:是否進行分類邏輯調換|只要低于正確率低于0.5則需要調換 % % output: % WeakLabel:由弱分類器進行的分類∈{+1,-1}% 閾值判斷 WeakLabel = ones(size(data,1),1); WeakLabel(data(:,dimension)<threshval)=-1; % 閾值判斷|邏輯調換if(exchange == -1)WeakLabel = -WeakLabel; end end一 數據集預處理
加載鳶尾花數據集前一百個樣本,包含了兩類,選取前維特征信息,該數據集是線性可分的。按照比例,將一百個樣本分為訓練集和測試集,不失一般性,每次都亂序排列。
二 訓練過程
1.在每一步中,對于每個特征都遍歷一個閾值,通過閾值判斷的方式進行分類,必定得到一個弱分類器(準確率大于0.5容易實現,若小于0.5,閾值判斷邏輯取反即可);
2.若滿足條件轉4(達到預設的迭代次數,或分類誤差率小于預設的允許值),否則繼續執行以下操作:遍歷時maintaining一個基于某維度特征的最佳閾值,其分類誤差率是最小的,稱之為最佳弱分類器(對于特定的一步);
3.由以上最佳弱分類器預測得到的label,計算該弱分類器的系數,以及下一步訓練中樣本的權值分布,回到2;
4.結束訓練,得到由弱分類器加權平均的強分類器。
三 測試過程
由最終的強分類器,得到每一個弱分類器的判斷依據(維度和相應的閾值),并根據判斷依據得到該弱分類器估計的label,將每一個弱分類器預計的label加權平均,作為sign函數的輸入,并將sign函數的輸出作為最終的輸出。
四 運行結果
運行結果如圖,準確率為96.7%.其中藍色點為識別錯誤的樣例。
適當提高訓練集數量,測試集準確率可達100%。如圖4-3與4-4.
代碼
clc;close;clear; %% 樣本初始化及可視化 [train_data,train_label,test_data,test_label,m1,n1,m2,n2] = data_init(0.5,100); drawTrain(train_data,train_label); %% 訓練 [weakClassifier,strongClassifierLabel,m]=train(train_data,train_label,1000); %% 測試 [Label] = test(weakClassifier,test_data,test_label,m); drawTest(test_data,test_label,Label); function [train_data,train_label,test_data,test_label,m1,n1,m2,n2] = data_init(k,data_num) % 功能說明:完成數據的預處理,setosa:1 versicolor:-1 % 調用語法及參數說明:[data_iris,data_label] = data_set(); % load('data_iris.mat');load('data_label.mat'); data_label = zeros(data_num,1); for i = 1:data_numswitch species(i)case 'setosa'data_label(i) = 1;case 'versicolor'data_label(i) = -1;end end data_iris = iris(1:data_num,:);% 亂序排列 randIndex = randperm(data_num); data_new=data_iris(randIndex,:); label_new=data_label(randIndex,:);% 分為兩組,比例k用于訓練,剩余用于測試 k = k*data_num; train_data=data_new(1:k,:); train_label=label_new(1:k,:); test_data=data_new(k+1:end,:); test_label=label_new(k+1:end,:); [m1,n1] = size(train_data); [m2,n2] = size(test_data);endfunction drawTest(test_data,test_label,Label) % 測試集及誤分類樣本可視化figure(2);hold on plot(test_data(test_label==1,1),test_data(test_label==1,2),'go','LineWidth',3,'MarkerSize',4); plot(test_data(test_label==-1,1),test_data(test_label==-1,2),'ro','LineWidth',3,'MarkerSize',4); plot(test_data(test_label~=Label,1),test_data(test_label~=Label,2),'bo','LineWidth',3,'MarkerSize',4); xlabel('x');ylabel('y'); title('測試集及誤分類樣本可視化');endfunction drawTrain(data,label) % 訓練集數據可視化figure(1);hold on plot(data(label==1,1),data(label==1,2),'go','LineWidth',3,'MarkerSize',4); plot(data(label==-1,1),data(label==-1,2),'ro','LineWidth',3,'MarkerSize',4); xlabel('x');ylabel('y'); title('訓練樣本');endfunction [bestWeakClassifier, minEm, bestLabel]=select(data,label,D) % 函數功能說明: % _找到一弱分類器,使得分類誤差率足夠小,此分類器工作機制為硬閾值判斷; % _此弱分類器是針對某一個特征進行閾值判斷 % _分類誤差率是考慮被分類錯誤的樣本,使其對應權值相加 % % input: % D:為權值分布,反映了上一次弱分類器的分類情況 % bestWeakClassifier:找到的最佳閾值和最佳特征 % minEm:最小(弱)分類誤差率 % bestLabel:最佳弱分類時,所進行的估計[m,n] = size(data); step = 10*m; % 閾值遍歷時需要設置步長,此處設置一個與數據樣本數相關的步長 bestWeakClassifier = []; % 最佳弱分類器 bestLabel = zeros(m,1); % 最佳的估計標簽 minEm = inf; % 最小誤差,初始化為無窮大for i=1:n % 按照不同特征作為分類依據進行分類minvalue = min(data(:,i));maxvalue = max(data(:,i));stepValue = (maxvalue-minvalue)/step; % 遍歷時的步長% 遍歷所有的數據取值for j = 0 : step % 閾值搜索的范圍為[minvalue,maxvalue]for exchange = -1:2:1 % 閾值判斷邏輯是否調換 threshval = minvalue + stepValue*j;WeakLabel = weakClassifier(data,i,threshval,exchange);% 錯誤數據為1,正確數據為0 || 計算em = Σw(誤分類樣本)errData = ones(m,1);errData(label == WeakLabel)=0;% 通過將D和勘誤相乘得到加權誤差em =D'*errData;% em = Σw(誤分類樣本):em:分類誤差率:分類錯誤的樣本的權值求和% 找到分類誤差率最小的閾值(分類器)if (em<minEm) % 記錄分類誤差最小的分類器基于的判斷特征+相應閾值+最小的誤差minEm = em;bestLabel = WeakLabel;bestWeakClassifier={'dimension' i;'thresh' threshval;'exchange' exchange};endendend end endfunction[Label] = test(weakClassifier,testData,testLabel,m) % 完成對測試集的測試num = size(testData,1); Label = []; for n = 1:numy = 0;for i = 0:m-1dimension = cell2mat(weakClassifier(i*4+1,2));thresh = cell2mat(weakClassifier(i*4+2,2));exchange = cell2mat(weakClassifier(i*4+3,2));alpha = cell2mat(weakClassifier(i*4+4,2));% 閾值邏輯判斷if(testData(n,dimension)>thresh)labell = 1;elselabell = -1;endlabell = labell * exchange;y = y + alpha * labell;endy = sign(y);Label = [Label;y]; end acc = sum(Label==testLabel)/size(testLabel,1); fprintf('在測試集上準確率為%f\n',acc); endfunction [weakClassifier,strongClassifier,i] = train(data,label,numIteration) % 參數及變量說明: % % input: % data:訓練樣本數據 % label:類別∈{+1,-1} % numIteration:迭代次數 % % output: % weakClassifier:一系列弱分類器 % err:錯誤分類率 % strongClassifier:強分類器(弱分類器的線性組合)得到的結果 % % % variable: % D:權值分布,初始化時為等權重(保證D始終是一個概率分布) % alpha:基本分類器的系數 % bestWeakClassifier:{'dimension';'thresh';'alpha'}m = size(data,1); weakClassifier = {}; D = ones(m,1)/m; % 初始化為等權重 combinedWeakClassifier = zeros(m,1);for i = 1:numIteration[bestWeakClassifier,minErr,bestLabel]=select(data,label,D);alpha= log((1-minErr)/minErr)/2;% 本次分類器對應的權重,為標量bestWeakClassifier(4,:) = {'alpha' alpha};% 存儲弱分類器參數weakClassifier=[weakClassifier;bestWeakClassifier];% 重新計算DD = D.*exp(-alpha*label.*bestLabel);D = D/sum(D);% 做歸一化處理% 弱分類器舉手表決(加權求和)combinedWeakClassifier = combinedWeakClassifier+alpha*bestLabel;% 強分類器strongClassifier = sign(combinedWeakClassifier);[~,err]=symerr(label,strongClassifier);% [number,ratio] = symerr(x,y)比較x和y。輸出ratio等于錯誤率。if(err <= 0.0001)break;end end fprintf('訓練集上準確率為:%f\n',1-err); endfunction [WeakLabel] = weakClassifier(data,dimension,threshval,exchange) % 函數功能:實現弱分類器(弱分類器) % input: % data:訓練樣本 % dimension:數據特征 % threshval:閾值,分類依據 % exchange:是否進行分類邏輯調換|只要低于正確率低于0.5則需要調換 % % output: % WeakLabel:由弱分類器進行的分類∈{+1,-1}% 閾值判斷 WeakLabel = ones(size(data,1),1); WeakLabel(data(:,dimension)<threshval)=-1; % 閾值判斷|邏輯調換if(exchange == -1)WeakLabel = -WeakLabel; end end總結
以上是生活随笔為你收集整理的基于Adaboost实现鸢尾花数据集分类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 支持向量机实现鸢尾花数据集分类matla
- 下一篇: 魔力宝贝手游不花钱怎么玩