K-Means
这一最著名的聚类算法主要基于数据点之间的均值和与聚类中心的距离迭代而成。它主要的优点是十分的高效,由于只需要计算数据点与聚类中心的距离,其计算复杂度只有O(n)。其工作原理主要分为以下四步:
k-means 算法接受输入量 k ;然后将n个 数据对象划分为 k个 聚类以便使得所获得的 聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。 聚类相似度是利用各聚类中对象的 均值所获得一个“中心对象”(引力中心)来进行计算的。
处理流程k-means 算法基本步骤
(1) 从 n个 数据对象任意选择 k 个对象作为初始聚类中心;
(2) 根据每个 聚类对象的 均值(中心对象),计算每个对象与这些中心对象的距离;并根据最小距离重新对相应对象进行划分;
(3) 重新计算每个(有变化) 聚类的 均值(中心对象);
(4) 计算标准测度函数,当满足一定条件,如函数收敛时,则算法终止;如果条件不满足则回到步骤
matlab中有kmeans函数直接可以调用
使用方法:
[Idx,C,sumD,D]=Kmeans(X,K)
各输入输出参数介绍:
X N*P的数据矩阵
K 表示将X划分为几类,为整数
Idx N*1的向量,存储的是每个点的聚类标号
C K*P的矩阵,存储的是K个聚类质心位置
sumD 1*K的和向量,存储的是类间所有点与该类质心点距离之和
D N*K的矩阵,存储的是每个点与所有质心的距离
这种方法在理解和实现上都十分简单,但缺点却也十分明显,十分依赖于初始给定的聚类数目;同时随机初始化可能会生成不同的聚类效果,所以它缺乏重复性和连续性。
算法实现1:
function [ idx, ctr ] = k_means( data, k, iterations )
%{
函数功能:
对数据实现k-means聚类
参数说明:
data:待聚类的数据,没有类别信息
k:期望聚类的类别数目
iterations:期望的算法的迭代次数(可不给)
算法停止的两个条件满足一个即可:达到预定迭代次数,聚类的质心不再改变或者改变很小。
函数返回:
idx:数据及其类别标号
ctr:存储k个聚类中的位置
%}
% m表示数据的规模,n表示数据的维度
[m, n] = size(data);
if k > m
disp('你需要聚类的数目已经大于数据的数目,无法聚类!');
return;
end
idx = zeros(m, 1);
ctr = zeros(k, n);
% nargin是用来判断输入变量个数的函数,这样就可以针对不同的情况执行不同的功能。
if nargin == 2
iterations = 0;
end
% 保存上一次的聚类中心
u = zeros(k, n);
% 保存更新后的聚类中心
c = zeros(k, n);
% 选定初始质心
t = 1;
for i=1:k
% 初始质心的选取方式为:从第一个数据开始,每隔m/k间隔选取一个数据点,直至得到k个类别中心
u(i, :) = data(t, :);
t = t + m/k;
end
iteration = 1;
while true
% 计算每个数据点到类别中心的距离,把数据点归入到与之最近的类别中
for i=1:m
% dis保存每个数据点到k个类别中心的距离
dis = zeros(k, 1);
for j=1:k
% 这里的数据可以是任意维度的,距离度量使用欧式距离
sum_dis = 0;
for t=1:n
sum_dis = sum_dis + (u(j, t) - data(i, t))^2;
end
dis(j) = sqrt(sum_dis);
end
% 找出数据点与k个类别中心中,距离最小的一个,该数据点归入到这一类中
[~, index] = sort(dis);
idx(i, 1:2) = data(i, :);
idx(i, 3) = index(1);
end
% 每一次聚类之后应该重新计算类别中心
for i=1:k
total_dis = zeros(1, n);
num_i = 0;
for j=1:m
if idx(j, 3) == i
for t=1:n
total_dis(1, t) = total_dis(1, t) + data(j, t);
end
num_i = num_i + 1;
end
end
c(i, :) = total_dis(1, :)/num_i;
end
% 算法结束
% 给定了迭代次数并且已经迭代了iterations次,退出算法
if iterations ~= 0 && iteration == iterations
ctr = c;
break;
elseif iterations == 0 && norm(c-u) < 0.01
ctr = c;
break;
end
iteration = iteration + 1; u = c;
end
end
算法实现2:
function KMeansv0(K,N,E,data,ff,cf)
%K=the number of clusters
%N=the maximum times of iteration
%E=the deviation theshold
%data=the pixel infor of figure
%ff=the feature selected
data=im2double(data);
r=data(:,:,1);
g=data(:,:,2);
b=data(:,:,3);
height=size(data,1);
width=size(data,2);
pixnum=height*width;
flag=zeros(pixnum,1);
samples=generatesamp(r,g,b,height,width,pixnum);
sampled=selectfeature(samples,ff);
oldcenter=centerselect(K,sampled,cf);
color=colorgenerate(K);
L=1;
%程序主体
while(1)
D=distfun(sampled,oldcenter);
for i=1:pixnum
j=find(D(i,:)==min(D(i,:)));
if size(j,2)>1
flag(i)=j(1);
else
flag(i)=j;
end
end
updatefig(flag,samples,color,data);
newcenter=recalcu(flag,sampled,K,oldcenter);
if L>=N
break;
else
L=L+1;
t=0;
for i=1:K
err=distfun(newcenter(i),oldcenter(i));
if err>=E
oldcenter(i,:)=newcenter(i,:); %%modified
else
t=t+1;
end
end
if t==K
break;
end
end
end
end
%%以下是自函数部分
function samples=generatesamp(r,g,b,height,width,pixnum)
% p=0;
% for i=1:height
% for j=1:width
% p=p+1;
% samples(p,:)=[r(i,j),g(i,j),b(i,j),i,j];
% end
% end
r1=reshape(r,height*width,1);
g1=reshape(g,height*width,1);
b1=reshape(b,height*width,1);
x=linspace(1,height,height);
x1=repmat(x',width,1);
y1=ones(pixnum,1); %%modified ,maybe improve speed
for i=2:width
y=ones(height,1).*i;
star=height*(i-1)+1;
stop=star+height-1;
y1(star:stop,1)=y(:,1);
end
samples=[r1 g1 b1 x1 y1];
end
function center=centerselect(k,sampled,cf)
%select the first K pixel as the origincenter
center=zeros(k,size(sampled,2));
switch cf
case 1 %select the first k sampled as center
for i=1:k
center(i,:)=sampled(i,:);
end
case 2 %select k centers randamly
% p=round(rand(k,1))*size(sampled,1)+1;
% center(:,:)=sampled(p',:);
case 3 %select k centers according to max(min)
s=round(rand*(size(sampled,1)/2))+1;
tempc(1,:)=sampled(s,:);
for j=2:k
d=distfun(sampled,tempc);
dmin=zeros(size(sampled,1),1);
for i=1:size(sampled,1)
dmin(i,1)=min(d(i,:));
end
% index=find(dmin==max(dmin)); %logical index is usually...
%faster than FIND
[dmax,index]=max(dmin);
tempc(j,:)=sampled(index,:);
end
center=tempc;
case 4 %select k centers according to mean and variance
m=mean(sampled);
v=std(sampled);
t1=m-v;
t2=m+v;
p=size(sampled,2);
for i=1:p
temp=linspace(t1(i),t2(i),k);
center(:,i)=temp';
end
end
end
function color=colorgenerate(k)
% r=[255 0 0];
% g=[0 255 0];
% b=[0 0 255];
% l1=linspace(1,0,k);
color=zeros(k,3);
% l2=rand(1,k);
for i=1:k
% color(i,:)=[round(rand(1,1)*255) round(rand(1,1)*255)...
% round(rand(1,1)*255)];
color(i,:)=[rand rand rand];
% color(i,:)=round(l1(i)*r)+round((1-l1(i))*g.*l2(i))...
% +round((1-l1(i))*b.*(1-l2(i)));
end
end
function sampled=selectfeature(samples,ff)
p=sum(ff);
flag=find(ff==1);
num=size(samples,1);
sampled=zeros(num,p);
% for i=1:num
% for j=1:p
% sampled(i,j)=samples(i,flag(j));
% end
% end
for j=1:p
sampled(:,j)=samples(:,flag(j)); %compared with above ,improve speed
end
end
function D = distfun(X, C)
%DISTFUN Calculate point to cluster centroid distances.
[n,p] = size(X);
D = zeros(n,size(C,1));
nclusts = size(C,1);
for i = 1:nclusts
D(:,i) = (X(:,1) - C(i,1)).^2;
for j = 2:p
D(:,i) = D(:,i) + (X(:,j) - C(i,j)).^2;
end
end
end
function updatefig(flag,samples,color,data)
[n,p]=size(samples);
for i=1:n
for j=1:3
samples(i,j)=color(flag(i),j);
data(samples(i,4),samples(i,5),j)=samples(i,j);
end
end
data=im2uint8(data);
% hold on
figure,imshow(data);
% hold off
end
function newcenter=recalcu(flag,sampled,k,oldcenter)
sumtemp=zeros(k,size(sampled,2));
aveg=zeros(k,size(sampled,2));
for i=1:k
tt=find(flag==i);
if size(tt,1)==0
aveg(i,:)=oldcenter(i,:);
continue;
end
num=size(tt,1);
temp=zeros(num,size(sampled,2));
for j=1:num
temp(j,:)=sampled(tt(j),:);
end
[n,p]=size(temp);
for l=1:p
sumtemp(i,l)=sum(temp(:,l));
aveg(i,l)=sumtemp(i,l)./n;
end
end
newcenter=aveg;
end