1. 程式人生 > >k-Means演算法Matlab實現

k-Means演算法Matlab實現

clc;
clear;
%讀取資料檔案,生成點矩陣
fileID = fopen('D:\matlabFile\data.txt');
 C=textscan(fileID,'%f %f');
 fclose(fileID);
 %顯示陣列結果
%celldisp(C);
 %將cell型別轉換為矩陣型別,這裡只假設原資料為二維屬性,且是二維的座標點
 CC_init=cat(2,C{1},C{2});%用來儲存初始載入的值
 CC=CC_init;
 %獲得物件的數量
 num=length(C{1});
 %顯示初始分佈圖
 %scatter(C{1},C{2},'filled');
 %%設定任意k個簇
k=3;
%臨時存放k箇中心點的陣列
C_temp=zeros(k,2);
%判斷所設定的k值是否小於物件的數量
if k<num
    %產生隨機的k個整數
   randC=randperm(num);
   randC=randC(1:k);
   %從原陣列中提出這三個點   
   for i=1:k
       C_temp(i,:)=CC(randC(1,i),:);
   end
   %將原陣列中的這三個點清空
    for j=1:k
       CC(randC(1,j),:)=zeros(1,2);
    end  
    idZero=find(CC(:,1)==0);
    %刪除為零的行
    [i1,j1]=find(CC==0);
    row=unique(i1);
    CC(row,:)=[];
   %分配k個二維陣列,用來存放聚類點
   %分配行為k的儲存單元
   cluster=cell(k,1,1); 
   %將剔除的三個點加入到對應的三個儲存單元,每個單元的第一行置為0,為了儲存相對應的簇中心
   for m=1:k
       cluster{m}=cat(1,zeros(1,2),C_temp(m,:));
   end
   %計算其他點到這k個點的距離,然後分配這些點,第一次遍歷
   for ii=1:num-k
       %分別計算到三個點的距離       
       minValue=1000000;%最小值,要根據實際情況設定該值
       minNum=-1;%最小值序號
       for jj=1:k
           if minValue>sqrt((CC(ii,1)-C_temp(jj,1))*(CC(ii,1)-C_temp(jj,1))+(CC(ii,2)-C_temp(jj,2))*(CC(ii,2)-C_temp(jj,2)))
               minValue=sqrt((CC(ii,1)-C_temp(jj,1))*(CC(ii,1)-C_temp(jj,1))+(CC(ii,2)-C_temp(jj,2))*(CC(ii,2)-C_temp(jj,2)));
               minNum=jj;
           end
       end
       cluster{minNum}=cat(1,cluster{minNum},CC(ii,:));       
   end
   %初次計算簇中心
   for n=1:k
       c=cluster{n};
       c(1,:)=[];
       cluster{n}(1,:)=mean(c,1);       
   end   
   %下面重複計算簇中心,直到沒有變化為止
   flag=1;
   count=0;
   while flag==1
       %將cluster除第一行之外的資料全部清空
       for i=1:k
           c=cluster{i}(1,:);
           cluster{i}=[];
           cluster{i}=c;
       end
       %把所有點重新分簇
       for j=1:num
           minValue=1000000;%最小值,要根據實際情況設定該值
           minNum=-1;%最小值序號
           for i=1:k
               if minValue>sqrt((CC_init(j,1)-cluster{i}(1,1))*(CC_init(j,1)-cluster{i}(1,1))+(CC_init(j,2)-cluster{i}(1,2))*(CC_init(j,2)-cluster{i}(1,2)))
                   minValue=sqrt((CC_init(j,1)-cluster{i}(1,1))*(CC_init(j,1)-cluster{i}(1,1))+(CC_init(j,2)-cluster{i}(1,2))*(CC_init(j,2)-cluster{i}(1,2)));
                   minNum=i;
               end
           end 
           cluster{minNum}=cat(1,cluster{minNum},CC_init(j,:)); 
       end
       %再次計算簇中心,並與原簇中心進行比較
       flag1=1;
       for n=1:k
           c_base=cluster{n}(1,:);
           c=cluster{n};
           c(1,:)=[];
           cluster{n}(1,:)=mean(c,1); 
           c_base=c_base-cluster{n}(1,:);
           if c_base~=0
               flag1=0;
           end            
       end 
       if flag1==0
           flag=1;
       else
           flag=0;
       end
       count=count+1;       
   end   
   %繪製聚類結果
   for i=1:k
       scatter(cluster{i}(:,1),cluster{i}(:,2),'filled');
       hold on
   end   
end