①获得所有样品特征
②设置阈值
③将所有样品各分一类,聚类中心等于样品总个数。
④对所有样品循环:
找到距离最近的两类pi,pj,设置距离minDis
若minDis<=T,则合并pi和pj否则退出循环。
clear all;close all;clc;
% 第一类数据
mu1=[0 0 ]; %均值
S1=[0.1 0 ;0 0.1]; %协方差
data1=mvnrnd(mu1,S1,100); %产生高斯分布数据
%第二类数据
mu2=[1.25 1.25 ];
S2=[0.1 0 ;0 0.1];
data2=mvnrnd(mu2,S2,100);
% 第三个类数据
mu3=[-1.25 1.25 ];
S3=[0.1 0 ;0 0.1];
data3=mvnrnd(mu3,S3,100);
% 显示数据
plot(data1(:,1),data1(:,2),'b+');
hold on;
plot(data2(:,1),data2(:,2),'r+');
plot(data3(:,1),data3(:,2),'g+');
grid on;
% 三类数据合成一个不带标号的数据类
data=[data1;data2;data3];
[m,n]=size(data);
patternNum=m;
T=0.1;
pattern=zeros(m,n+1);
for i=1:patternNum
pattern(i,n+1)=i;
pattern(i,1:n)=data(i,:);
end
while 1
minDis=inf;
pi=0;
pj=0;
% 寻找距离最近的两个类计算最小距离
for i=1:patternNum-1
for j=i+1:patternNum
if(pattern(i,n+1)~=pattern(j,n+1))
tempDis=norm(pattern(i,1:n)-pattern(j,1:n));
if(tempDis
minDis=tempDis;
pi=pattern(i,n+1);
pj=pattern(j,n+1);
end
end
end
end
% 距离小于阈值则合并两个类
if(minDis<=T)
if(pi>pj)
temp=pi;
pi=pj;
pj=temp;
end
for i=1:patternNum
if(pattern(i,n+1)==pi)
pattern(i,n+1)=pi;
elseif(pattern(i,n+1)>pi)
pattern(i,n+1)=pattern(i,n+1)-1;
end
end
else
break;
end
end
disp('ok')
[m, n]=size(pattern);
%最后显示聚类后的数据
figure;
hold on;
for i=1:m
if pattern(i,n)==1
plot(pattern(i,1),pattern(i,2),'r*');
elseif pattern(i,n)==2
plot(pattern(i,1),pattern(i,2),'g*');
elseif pattern(i,n)==3
plot(pattern(i,1),pattern(i,2),'b*');
elseif pattern(i,n)==4
plot(pattern(i,1),pattern(i,2),'y*');
else
plot(pattern(i,1),pattern(i,2),'m*');
end
end
grid on;
下图是产生的高斯数对及当阈值设置为T=0.1的时候的结果:
当T=0.5时的结果:
可见当阈值设的比较大时所有的都将成为一类。所以阈值的设置很重要。
基于最小距离的层次聚算法对类间距要求很高,例如将高斯数对的协方差加大,产生距离比较近的数对时,层次聚类算法就会出现很大问题如下图:
但是在相同的生成参数下,kmeans却有很好的效果: