天天看點

基于改進人工蜂群算法的K均值聚類算法(Matlab代碼實作)

💥💥💥💞💞💞歡迎來到本部落格❤️❤️❤️💥💥💥

🏆部落客優勢:🌞🌞🌞部落格内容盡量做到思維缜密,邏輯清晰,為了友善讀者。

⛳️座右銘:行百裡者,半于九十。

目錄

​​💥1 概述​​

​​📚2 文獻來源​​

​​🎉3 運作結果​​

​​👨‍💻4 Matlab代碼實作​​

💥1 概述

針對K均值聚類(KMC)算法全局搜尋能力差、初始聚類中心選擇敏感,以及原始人工蜂群(ABC)算法的初始化随機性﹑易早熟、後期收斂速度慢等問題,提出了一種改進人工蜂群算法( IABC)。該算法利用最大最小距離積方法初始化蜂群,構造出适應KMC算法的适應度函數以及一種基于全局引導的位置更新公式以提高疊代尋優過程的效率。将改進的人工蜂群算法與KMC算法結合提出IABC-Kmeans算法以改善聚類性能。通過Sphere 、Rastrigin、Rosenbrock 和Griewank 四個标準測試函數和UCI标準資料集上進行測試的仿真實驗表明,IABC算法收斂速度快,克服了原始算法易陷入局部最優解的缺點; IABC-Kmeans算法則具有更好的聚類品質和綜合性能。

📚2 文獻來源

基于改進人工蜂群算法的K均值聚類算法(Matlab代碼實作)

🎉3 運作結果

基于改進人工蜂群算法的K均值聚類算法(Matlab代碼實作)
function [Colony Obj Fit oBas]=GreedySelection(Colony1,Colony2,ObjEmp,ObjEmp2,FitEmp,FitEmp2,fbas,ABCOpts,i)
oBas=fbas;
 Obj=ObjEmp;
 Fit=FitEmp;
 Colony=Colony1;
 if (nargin==8)%Inside the body of a user-defined function, NARGIN returns the number of input arguments that were used to call the function. 
 for ind=1:size(Colony1,1)%ind=1:5,對所有食物源進行貪婪選擇
     if (FitEmp2(ind)>FitEmp(ind))%如果Vi的适應度值大于Xi的,替換,,
         oBas(ind)=0;
          %zj因為這是已經被新的位置更新了,是以其開采度應該置為零,表示這是第一次,沒有被開采過
         Fit(ind)=FitEmp2(ind);
         Obj(ind)=ObjEmp2(ind);
         Colony(ind,:)=Colony2(ind,:);
     else%否則不變,并且計數器bas+1
         oBas(ind)=fbas(ind)+1;
          %zj因為新的位置的适應度沒有目前的好(大),是以在目前位置上仍保留目前解,表示目前又被開采了一次
         Fit(ind)=FitEmp(ind);
         Obj(ind)=ObjEmp(ind);
         Colony(ind,:)=Colony1(ind,:);
     end;
 end; %for
 end; %if
 if(nargin==9)%第i個引領蜂被跟随,隻對第i個食物源進行貪婪選擇
     ind=i;
     if (FitEmp2(ind)>FitEmp(ind))
         oBas(ind)=0;
         Fit(ind)=FitEmp2(ind);
         Obj(ind)=ObjEmp2(ind);
         Colony(ind,:)=Colony2(ind,:);
     else
         oBas(ind)=fbas(ind)+1;
         Fit(ind)=FitEmp(ind);
         Obj(ind)=ObjEmp(ind);
         Colony(ind,:)=Colony1(ind,:);
     end;
 end; 
     GlobalMins=zeros(ABCOpts.RunTime,ABCOpts.MaxCycles);
for r=1:ABCOpts.RunTime
     
 % Initialise population
 Range = repmat((ABCOpts.ub-ABCOpts.lb),[ABCOpts.ColonySize ABCOpts.Dim]);
 Lower = repmat(ABCOpts.lb, [ABCOpts.ColonySize ABCOpts.Dim]);
 Colony = rand(ABCOpts.ColonySize,ABCOpts.Dim) .* Range + Lower;%生成初始Colony,其中ColonySize行,Dim列,10*5
 %zj先初始化種群規模。。。這個就是算法中式子:x(j)i=x(j)min+rand(0,1)(x(j)max-x(j)min)Employed=Colony(1:(ABCOpts.ColonySize/2),:);%前一半為引領蜂或食物源,5*5
 %zj再将種群的前一半作為引領蜂規模%evaluate and calculate fitness
 ObjEmp=feval(ABCOpts.ObjFun,Employed);%計算引領蜂組Employed的每一行(每一個食物源Xi)的目标函數值,1*5
 FitEmp=calculateFitness(ObjEmp);%計算食物源的适應度值,1*5%set initial values of Bas
 Bas=zeros(1,(ABCOpts.ColonySize/2));%1*5,每一列對應每一個Xi沒有被更新的次數 GlobalMin=ObjEmp(find(ObjEmp==min(ObjEmp),end));%不帶end結果一樣,因為ObjEmp為一個列向量,找出目标函數ObjEmp中最小的值給了GlobalMin,1*1
 GlobalParams=Employed(find(ObjEmp==min(ObjEmp),end),:);%GlobalParams存放目标函數ObjEmp最小時對應的解,1*5Cycle=1;
 while ((Cycle <= ABCOpts.MaxCycles)),%開始循環
     
     %%%%% Employed phase
     Employed2=Employed;%Employed2的每一行對應于Employed每一行的鄰域搜尋值,即Employed每一行代表Xij,Employed2每一行代表Vij
     for i=1:ABCOpts.ColonySize/2%對Xij的每一個i,隻有一個j改變。
         Param2Change=fix(rand*ABCOpts.Dim)+1;%對應于j
         %zj這就是算法中要找的xij中的j,其是Dim中的一個随機數
         neighbour=fix(rand*(ABCOpts.ColonySize/2))+1;%對應于k
             while(neighbour==i)
                 neighbour=fix(rand*(ABCOpts.ColonySize/2))+1;
             end;
              %zj因為k不能取和i相同的值,是以這裡如果取到的k正好等于i,那麼将重新随機選取一個值
         Employed2(i,Param2Change)=Employed(i,Param2Change)+(Employed(i,Param2Change)-Employed(neighbour,Param2Change))*(rand-0.5)*2;
         %不能超過上下界
        %zj這個就是算法中式子:vij=xij+suijishu(xij-xkj),上式中(rand-0.5)*2就是為了限制suijishu的範
        %圍控制在(-1,1)之間的
         if (Employed2(i,Param2Change)<ABCOpts.lb)
              Employed2(i,Param2Change)=ABCOpts.lb;
          end;
         if (Employed2(i,Param2Change)>ABCOpts.ub)
             Employed2(i,Param2Change)=ABCOpts.ub;
         end;
          %zj可能出于規範的考慮,前面設定了參數lb和ub就是用來限定新的位置不應該越界,如果比下限小,則将下限賦給它,如果比上限大
         %則将上線賦給它
 end;       ObjEmp2=feval(ABCOpts.ObjFun,Employed2);%計算每一個Vi的目标函數值,5*1
     FitEmp2=calculateFitness(ObjEmp2);%計算每一個Vi的适應度值,5*1
     [Employed ObjEmp FitEmp Bas]=GreedySelection(Employed,Employed2,ObjEmp,ObjEmp2,FitEmp,FitEmp2,Bas,ABCOpts);
      %zj  Employed:之前的位置數組;   Employed2:更新位置後的數組;   
     %ObjEmp:之前的目标函數值(每隻蜜蜂);    ObjEmp2:更新位置後的目标函數值(即每隻蜜蜂的函數值)
     %Bas:表示被開采的次數;   ABCOpts:整個結構體zj
     
     %貪婪原則選擇,Employed ObjEmp FitEmp分别對應選擇後的食物源,函數值和适應度
     %Normalize
     NormFit=FitEmp/sum(FitEmp);%50*1,每一行對應于Xi和Vi較優解的Pi
     
     %%% Onlooker phase  
 Employed2=Colony((ABCOpts.ColonySize/2)+1:ABCOpts.ColonySize,:);
 %zj本來這句是Employed2=Employed;但是通過本人閱讀論文來看,一般情況是總樣本數=引領蜂數量+跟随蜂數量;引領蜂數量=跟随蜂數量;并
 %且,引領蜂是前50%,跟随蜂是後50%zj
 i=1;
 t=0;
 while(t<ABCOpts.ColonySize/2) 
     %輪盤賭
     if(rand<NormFit(i))%NormFit(i)越大,被選中的次數越多
         t=t+1;%所有跟随蜂都必須選擇引領蜂進行跟随
         Param2Change=fix(rand*ABCOpts.Dim)+1;
         neighbour=fix(rand*(ABCOpts.ColonySize/2))+1;
             while(neighbour==i)
                 neighbour=fix(rand*(ABCOpts.ColonySize/2))+1;
             end;
          Employed2(i,:)=Employed(i,:);%引領蜂被選中跟随,Employed2(i)為跟随蜂
          %跟随蜂進行鄰域搜尋
          Employed2(i,Param2Change)=Employed(i,Param2Change)+(Employed(i,Param2Change)-Employed(neighbour,Param2Change))*(rand-0.5)*2;
          if (Employed2(i,Param2Change)<ABCOpts.lb)
              Employed2(i,Param2Change)=ABCOpts.lb;
          end;
         if (Employed2(i,Param2Change)>ABCOpts.ub)
             Employed2(i,Param2Change)=ABCOpts.ub;
          end;
     ObjEmp2=feval(ABCOpts.ObjFun,Employed2);%計算跟随蜂鄰域搜尋解的目标函數
     FitEmp2=calculateFitness(ObjEmp2);%計算跟随蜂鄰域搜尋解的适應度
     [Employed ObjEmp FitEmp Bas]=GreedySelection(Employed,Employed2,ObjEmp,ObjEmp2,FitEmp,FitEmp2,Bas,ABCOpts,i);
    
    end;
     
     i=i+1;
     if (i==(ABCOpts.ColonySize/2)+1)  %如果超出範圍,将i至1
         i=1;
     end;   
 end;
     
     
     %%%Memorize Best
  CycleBestIndex=find(FitEmp==max(FitEmp));
  CycleBestIndex=CycleBestIndex(end);%我認為可以不要
  CycleBestParams=Employed(CycleBestIndex,:);%原本注釋是“求每次循環中适度值最小所對應的食物源(解)”我認為是“求每次循環中适度值最大所對應的食物源(解)”
  CycleMin=ObjEmp(CycleBestIndex);%原本這句注釋是“求每次循環中适度值最小所對應的函數值”,我認為是“求每次循環中适度值最大所對應的函數值”
  
  if CycleMin<GlobalMin %和全局最小進行比較
        GlobalMin=CycleMin;
        GlobalParams=CycleBestParams;
  end
  
  GlobalMins(r,Cycle)=GlobalMin;%記錄每次循環所對應的全局最小值,1*2000
  
  %% Scout phase
  ind=find(Bas==max(Bas));%找到沒有被更新次數最多的那個食物源Xi,并把次數和limit比較
 ind=ind(end);
 if (Bas(ind)>ABCOpts.Limit)
 Bas(ind)=0;
 %Employed(ind,:)=(ABCOpts.ub-ABCOpts.lb)*(0.5-rand(1,ABCOpts.Dim))*2+ABCOpt
 %s.lb;
 Employed(ind,:)=(ABCOpts.ub-ABCOpts.lb)*(0.5-rand(1,ABCOpts.Dim))*2;%+ABCOpts.lb;
 %        Employed2(i,Param2Change)=Employed(i,Param2Change)+(Employed(i,Par
 %        am2Change)-Employed(neighbour,Param2Change))*(rand-0.5)*2;
 %message=strcat('burada',num2str(ind))
 end;
 ObjEmp=feval(ABCOpts.ObjFun,Employed);
 FitEmp=calculateFitness(ObjEmp);
          fprintf('Cycle=%d ObjVal=%g\n',Cycle,GlobalMin);
     
     Cycle=Cycle+1;end % End of ABC
end; %end of runs
 if ABCOpts.RunTime==1
     %semilogy(GlobalMins,'b');
 else
     %semilogy(mean(GlobalMins),'b');%若多次執行,求均值
 end
 %semilogy(mean(GlobalMins))
 % title('Mean of Best function values');
 % xlabel('cycles');
 % ylabel('error');
 fprintf('Mean =%g Std=%g\n',mean(GlobalMins(:,end)),std(GlobalMins(:,end)));%輸出GlobalMins的均值和方差      

👨‍💻4 Matlab代碼實作

繼續閱讀