K-mean 属于传统的聚类算法,如果给一组数据,我们知道这些数据能分成C类,但是每个类的中心位置在哪里呢?K-mean的思路是,首先不管你的数据什么样,我就认为它们服从均匀分布,把数据在最小值、最大值之间分成K等份,有了这个K个聚类中心,然后计算每个数据到这K个聚类中心的距离,假设我们一共有N个数据,就生成了一个N*K的矩阵,每一行代表一个数据与所有聚类中心的距离,接着你肯定想,哪个聚类中心跟我距离近,我就自动投入怀抱,对!这就是找到新的聚类中心的第一步---找到每个数据最近的聚类,再下来,考虑这种情况,有5个数据都属于类别9,在9的左侧有4个数,右边只有1个数,那么聚类中心应该向左移动一下才能体现这5个数的实际情况,算法就是类似的思想,把刚才我对每个数据的归类拿出来,开始轮个计算,属于类别1有几个数,他们位置多少,然后让这几个数位置相加,除以属于类别1的数据个数,就得到类别1的新的聚类中心,这就是均值的概念,然后考察类别2...直到你把所有类别都更新一遍,就是一组全新的聚类中心,把这个新的聚类与上一次就得聚类做差,当前后的聚类小于范围(limit)时,可以认为当前的聚类已经足够好,可以停止,如果这组类别还不够满意,你就接着计算N*K矩阵....重复寻找。
1.函数定义
function [K_center]=kmean(data,K,LOOP)% data是待分类的数据,尺寸为 (dim*N),dim代表每个样本的维数,N代表样本个数
% K 是设定的聚类数量,即把N个样本分成K类,每一类内部的差别小,各类之间的差别大
%首先,确定K个初始聚类中心,这些聚类中心均来源于原始的N个样本
[dim,N]=size(data);
K_center=zeros(dim,K);
for d=1:1:dim
ma=max(data(d,:));mi=min(data(d,:));
section=(ma-mi)/(2*K);
for k=1:1:K
K_center(d,k)=mi+(2*k-1)*section;
end
end
%所有的K个初始聚类中心已经确定,下面按照传统的kmeans算法执行
for loop=1:1:LOOP
DIS=zeros(K,N); %计算N个样本与K个聚类之间的距离,行代表聚类,列代表样本
for i=1:1:N
for j=1:1:K
d=K_center(:,j)-data(:,i);
DIS(j,i)=d'*d;
end
end
class=zeros(1,N);
for i=1:1:N
class(1,i)=1;
d=DIS(1,i);
for j=1:1:K
if DIS(j,i)<d
d=DIS(j,i);
class(1,i)=j;
end
end
end
for k=1:1:K
sum=zeros(dim,1);
idx=find(class==k);
count=length(idx);
for c=1:1:count
sum=sum+data(:,idx(c));
end
K_center(:,k)=sum/count;
end
end
2.函数运行测试
[data,w,m,s]=Gauss_sample(2,6,100);
figure(1);clf
plot(data(1,:),data(2,:),'b*');
hold onk_center=Kmean(data,6,100);
原始高斯分布的100个数据的真实聚类中心 m=
-24 -88 -78 12 -22 3
-22 -32 -36 17 -15 46
经过Kmean算法计算得到的聚类中心 k_center=
-92.2370 -76.6453 -30.7735 -20.5398 11.4017 3.1334
-30.0264 -35.4858 -27.1757 -15.2068 16.6982 46.3315
算法效果还不错,下面一幅图显示结果,蓝色星星是原始的高斯数据,红色圆圈是kmean计算的聚类中心