實驗目的
(1)理解聚類算法的基本原理。
(2)掌握kmeans聚類算法的原理與實現。
實驗內容
1、數據見 data.mat
,編程實現 K means
算法代碼 K_MeansMt
,並寫出詳細註釋。
測試代碼如下:
load 'data.mat';
[u re]=K_MeansMt(data,3); %最後產生簇標號 re
[m n]=size(re);
%最後顯示聚類後的數據
figure;
hold on;
for i=1:m
if re(i)==1
plot(data(i,1),data(i,2),'ro');
elseif re(i)==2
plot(data(i,1),data(i,2),'go');
else
plot(data(i,1),data(i,2),'bo');
end
end
grid on;
測試數據
數據見 data.mat
鏈接: https://pan.baidu.com/s/1vRSaZVzEI69ING6IQWJ-zA
提取碼: 338y
實驗原理
基本K均值算法
K均值的算法步驟
- 首先選擇K個初始質心,其中K是用戶指定的參數,即所期望的簇的個數。每個點指派到最近的質心,而指派到一個質心的點集爲一個簇。
- 然後,根據指派到簇的點,更新每個簇的質心。
- 重複指派和更新步驟,直到簇不發生變化,或等價的,直到質心不發生變化。
算法流程如下:
- 選擇
k
個點作爲初始質心 - repeat:
- 將每個點指派到最近的質心,形成
k
個簇 - 重新計算每個簇的質心
- until 質心不發生變化
對於鄰近性函數和質心類型的某些組合,k均值總是收斂到一個解,即k均值到達一種狀態,其中所有點都不會從一個簇轉移到另一個,因此質心不再改變。然而,由於大部分收斂都發生在早期階段,因此通常用較弱的條件替換算法(上述第5行)。例如,用“直到僅有1%的點改變簇”。
實驗代碼
%%k表示數據一共分多少類
%%data是輸入的不帶分類標號的數據
%%u是每一類的中心
%%clusterID是返回的帶分類標號的數據
function [u clusterID] = K_MeansMt(data,k)
[m n] = size(data); %m是數據個數,n是數據維數
maxn = zeros(1,n); %每一維最大的數
minn = zeros(1,n); %每一維最小的數
u = zeros(k,n); %隨機初始化,最終迭代到每一類的中心位置
for i=1:n
maxn(i) = max(data(:,i)); %每一維最大的數
minn(i) = min(data(:,i)); %每一維最小的數
for j=1:k
u(j,i) = minn(i)+(maxn(i)-minn(i))*rand(); %隨機初始化,保證處於[minn,maxnn]之間
end
end
while 1
pre_u = u; %上一次求得的質心位置
coordinate_difference{m,k} = [];
for i=1:m
% data(i,:)-u(j,:) 爲計算質心做準備
for j=1:k
coordinate_difference{i,j} = data(i,:) - u(j,:);
end
end
Dist = ones(m,k)*-1;
for i=1:m %計算質心
c=zeros(1,k);
for j=1:k
c(j) = norm(coordinate_difference{i,j});
end
[cmin index] = min(c); %%哪個類的距離最小(index爲類號)
Dist(i,index) = norm(coordinate_difference{i,index});
end
for i=1:k
ind = find(Dist(:,i)>=0);
u(i,:) = mean(data(ind,:));
end
if(norm(pre_u - u)<0.1) %不斷迭代直到位置不再變化
break;
end
end
clusterID = [];
for i=1:m
dist = [];
for j=1:k
dist = [dist norm(data(i,:)-u(j,:))]; %每個點到穩定後的類中心的距離
end
[x index] = min(dist); %%選擇距離最小的類別號
clusterID = [clusterID;index];
end
end
實驗結果
學如逆水行舟,不進則退