hierachical clustering系统聚类算法,将模式样本按距离准则逐步分类,类别由多到少(初始是每个样本一个类别),直到获得合适的分类要求为止。主要参照了蔡元龙老师的《模式识别一书》。
该算法如下:
第一步:设初始模式样本共有N个,每个样本自成一类,即建立N类,。计算各类之间的距离(初始时即为各样本间的距离),得到一个N*N维的距离矩阵D(0)。这里,标号(0)表示聚类开始运算前的状态。
第二步:假设前一步聚类运算中已求得距离矩阵D(n),n为逐次聚类合并的次数,则求D(n)中的最小元素。如果它是Gi(n)和Gj(n)两类之间的距离,则将Gi(n)和Gj(n)两类合并为一类 ,由此建立新的分类: 。
第三步:计算合并后新类别之间的距离,得D(n+1)。
计算 与其它没有发生合并的 之间的距离,可采用多种不同的距离计算准则进行计算。
第四步:返回第二步,重复计算及合并,直到得到满意的分类结果。(如:达到所需的聚类数目,或D(n)中的最小分量超过给定阈值D等。
matlab程序编写:
%Programed by Lu Qi,University of Chinese Academy of Sciences
%my email:qqlu1992@gmail.com
clear all
clc
% train_x=[0 3 1 2 0;
% 1 3 0 1 0;
% 3 3 0 0 1;
% 1 1 0 2 0;
% 3 2 1 2 1;
% 4 1 1 1 0];
train_x=[0 1 3 1 3 4;
3 3 3 1 2 1;
1 0 0 0 1 1;
2 1 0 2 2 1;
0 0 1 0 1 0
];
[pars.num_train,pars.length]=size(train_x);%initial代表样本的数量,length代表样本的维数
pars.num_cluster=2;
pars.iter=pars.num_train-pars.num_cluster;
train_y=1:pars.num_train';
for i=1:pars.num_train
pars.g{i}=[train_y(i)];
end
pars.box={pars.g};
for i=1:pars.num_train
for j=1:i
euclidean(i,j)=norm(train_x(i,:)-train_x(j,:));
end
end
for i=1:pars.iter
if i==1
[pars,new_euclidean{i}]=hierar_clus(pars,euclidean,euclidean);
else
[pars,new_euclidean{i}]=hierar_clus(pars,new_euclidean{i-1},euclidean);
end
end
其中程序中用到了自己编写的程序[pars,d]=hierar_clus(pars,new_euclidean,euclidean),该程序如下:
function [pars,d]=hierar_clus(pars,new_euclidean,euclidean)
%Programed by Lu Qi,University of Chinese Academy of Sciences
%my email:qqlu1992@gmail.com
% input pars:各类参数
% new_euclidean:每次合并之后的新矩阵
% euclidean:刚开始时的距离矩阵
% output d:新形成的距离矩阵
% g:新形成的聚类盒子
[x,y]=size(new_euclidean);
new_euclidean(find(new_euclidean==0))=max(new_euclidean(:))+1;
nimn=min(new_euclidean(:));
[irowmin,icolmin]=find(new_euclidean==min(new_euclidean(:)));
pars.g{min(irowmin,icolmin)}=[pars.g{min(irowmin,icolmin)} pars.g{max(irowmin,icolmin)}];
pars.g(max(irowmin,icolmin))=[];
new_euclidean(find(new_euclidean==(max(new_euclidean(:)))))=0;
box_length=length(pars.g);
pars.box(end+1)={pars.g};
for i=1:box_length
for j=1:i
first_length=length(pars.g{i});
second_length=length(pars.g{j});
for p=1:first_length
for q=1:second_length
if pars.g{i}(p)<pars.g{j}(q)
temp(p,q)=euclidean(pars.g{j}(q),pars.g{i}(p));
else
temp(p,q)=euclidean(pars.g{i}(p),pars.g{j}(q));
end
end
end
d(i,j)=min(temp(:));
temp(:)=[];
end
end
g=pars.g;