原理
給定一系列樣本點,想要分成k類
(1)首先從中隨機選取k個點作為質心
(2)分別計算每個點到這k個質心的歐式距離(為例),到哪個質心距離最小,這個點就屬於這個質心,這樣把所有點分成k類
(3)再分別計算k類中每一類新的質心,根據公式2
(4)迭代(2)(3),直到達到最優條件,條件如最小距離平方和公式3;
公式1公式2
公式3
close all;
clc;
%第一類資料
mu1=[0 0 0]; %均值
s1=[0.3 0 0;0 0.35 0;0 0 0.3]; %協方差
data1=mvnrnd(mu1,s1,100); %產生高斯分布資料
%%第二類資料
mu2=[1.25 1.25 1.25];
s2=[0.3 0 0;0 0.35 0;0 0 0.3];
data2=mvnrnd(mu2,s2,100);
%第三個類資料
mu3=[-1.25 1.25 -1.25];
s3=[0.3 0 0;0 0.35 0;0 0 0.3];
data3=mvnrnd(mu3,s3,100);
%顯示資料
plot3(data1(:,1),data1(:,2),data1(:,3),'+');
hold on;
plot3(data2(:,1),data2(:,2),data2(:,3),'r+');
plot3(data3(:,1),data3(:,2),data3(:,3),'g+');
grid on;
%三類資料合成乙個不帶標號的資料類
data=[data1;data2;data3]; %這裡的data是不帶標號的
%k-means聚類
[u re]=kmeans(data,3); %最後產生帶標號的資料,標號在所有資料的最後,意思就是資料再加一維度
[m n]=size(re);
%最後顯示聚類後的資料
figure;
hold on;
for i=1:m
if re(i,4)==1
plot3(re(i,1),re(i,2),re(i,3),'ro');
elseif re(i,4)==2
plot3(re(i,1),re(i,2),re(i,3),'go');
else
plot3(re(i,1),re(i,2),re(i,3),'bo');
endendgrid on;
kmeans.m
%n是資料一共分多少類
%data是輸入的不帶分類標號的資料
%u是每一類的中心
%re是返回的帶分類標號的資料
function [u re]=kmeans(data,n)
[m n]=size(data); %m是資料個數,n是資料維數
ma=zeros(n); %每一維最大的數
mi=zeros(n); %每一維最小的數
u=zeros(n,n); %隨機初始化,最終迭代到每一類的中心位置
for i=1:n
ma(i)=max(data(:,i)); %每一維最大的數
mi(i)=min(data(:,i)); %每一維最小的數
for j=1:n
u(j,i)=ma(i)+(mi(i)-ma(i))*rand(); %隨機初始化,不過還是在每一維[min max]中初始化好些
end
endwhile 1
pre_u=u; %上一次求得的中心位置
for i=1:n
tmp=; % 公式一中的x(i)-uj,為公式一實現做準備
for j=1:m
tmp=[tmp;data(j,:)-u(i,:)];
endend
quan=zeros(m,n);
for i=1:m %公式一的實現
c=;for j=1:n
c=[c norm(tmp(i,:))];
end[junk index]=min(c);
quan(i,index)=norm(tmp(i,:));
endfor i=1:n %公式二的實現
for j=1:n
u(i,j)=sum(quan(:,i).*data(:,j))/sum(quan(:,i));
end
endif norm(pre_u-u)<0.1 %不斷迭代直到位置不再變化
break;
endend
re=;
for i=1:m
tmp=;
for j=1:n
tmp=[tmp norm(data(i,:)-u(j,:))];
end[junk index]=min(tmp);
re=[re;data(i,:) index];
endend
c++實現
#include #include #include #include #include #include #define k 3//簇的數目
using namespace std;
//存放元組的屬性資訊
typedef vectortuple;//儲存每條資料記錄
int datanum;//資料集中資料記錄數目
int dimnum;//每條記錄的維數
//計算兩個元組間的歐幾裡距離
double getdistxy(const tuple& t1, const tuple& t2)
return sqrt(sum);
}//根據質心,決定當前元組屬於哪個簇
int clusteroftuple(tuple means,const tuple& tuple)
} //cout<
} for(int j=1; j<=dimnum; ++j)
t[j] /= num;
return t;
//cout<
tuples.push_back(tuple);
} cout<
聚類演算法之Kmeans
kmeans是聚類演算法中比較簡單的演算法,也用的非常多。這裡進行簡單的解釋,主要目的在於給自己記錄,以備以後檢視。k均值聚類的主要思想是為了使得各個類的點離聚類中心都盡可能近。k均值聚類的演算法可以描述為 輸入 資料集d d 聚類簇個數 k 演算法 從資料集d中隨機選擇k個樣本作為初始聚類中心 r...
聚類演算法之K means
k means演算法也稱k 均值聚類演算法。它試圖通過基於原型的 劃分的距離計算來發現k個使用者預先指定的簇。將一組資料劃分為預先設定好的k個簇,也可理解為隨機選擇k個向量作為初始均值向量。接下來根據均值向量將樣本劃分到距離最近的均值向量所在的簇中。這是一次迭代過程。重新計算並更新均值向量,不斷重複...
聚類演算法之K Means演算法
對大量未進行標註 unsupervised learning 的資料集,並按照資料集本身的內部資料特徵將資料劃分為多個不同的類別,從而使得類別內的資料相似度高,而類別間的資料差異性較大。因此,它的重點就在於計算樣本間的相似度 similarity 輸入演算法所需資料,資料樣本集d 將樣本資料集分開的...