基于样本空间分布密度的初始聚类中心优化K-均值算法matlab实现
- 该算法充分利用数据集样本的空间分布信息,根据数据集的样本分布特征划分数据集,启发式地确定初始聚类中心,避免了传统K-均值算法的聚类中心随机选取,并利用样本的空间分布信息尽可能地避免现有相关算法的主观性。
- 下面为该算法简单的matlab实现
function [M,Classify] = k_means(data,K,cR)
% 输入需要进行聚类的数据、k值、Rc值,输出中心
% (1)初始化中心点
% step1
% 获得数据的数量和维度
datas = data;
[datas_rows, datas_cols] = size(datas);
[data_rows, data_cols] = size(data);
% 初始化对象xi的密度值
Density = zeros(1,datas_rows);
% 初始化中心点集M
M=[];
% 计算xi的Density
% 计算sum_d(xl,xj),存到一个新的矩阵中,每个元素代表一个的d(xl,xj)
data_lj=[];
for i=1:datas_rows
temp=(data(i,:)-data).^2;
dlj_sum = sum(sqrt(sum(temp,2)));
data_lj=[data_lj;dlj_sum];
end
for i=1:datas_rows
D=0;
% 计算d(xi,xj)
temp=(data(i,:)-data).^2;
% 求矩阵的各行之和
dij = sqrt(sum(temp,2));
Density(i)=sum(dij./data_lj);
end
% 对Density进行升序
[Density_ascend, index]=sort(Density);
% step2
% 计算DistMean
Dij_norepeat=0;
for i=1:data_rows
temp=(data(i,:)-data(i:data_rows,:)).^2;
dij_norepeat=sum(sqrt(sum(temp,2)));
Dij_norepeat=Dij_norepeat+dij_norepeat;
end
DistMean=2/(data_rows*(data_rows-1))*Dij_norepeat;
% 计算半径R
R=DistMean/((data_rows)^cR);
% 将xi按照Density进行排序
datas_sort=[];
for i=1:data_rows
datas_sort=[datas_sort;data(index(i),:)];
end
[datas_sort_rows,datas_sort_cols]=size(datas_sort);
% 选取初始中心点
while true
% 选出初始中心点
initial_point=datas_sort(1,:);
% 将初始点加到M中
M=[M;initial_point];
% 在原数据中删除选出的初始中心点
datas_sort(1,:)=[];
datas_sort_rows=datas_sort_rows-1;
% 计算数据集中任意两个不同样本间的距离之和
% 删去领域中的数据样本点
temp=(initial_point-datas_sort).^2;
diq = sqrt(sum(temp,2));
% 删去数据中小于R的元素
less_index=find(diq<R);
datas_sort(less_index,:)=[];
% step3,step4
% 如果M中包含样本点为K则停止
[len_,shape_]=size(M);
if len_==K
% 输出初始中心点集M
break;
end
end
% (2)更新类簇中心点,(3)分配数据
% step1
% 初始化数据点与聚类中心的距离
D=zeros(data_rows,K);
% 初始化聚类误差平方和
bias=[0,1];
% 定义迭代结束的阈值
eps=1e-5;
times=1;
error=0;
% 判断的条件时前后两次的聚类误差平方和是否小于某个阈值
while abs(bias(2)-bias(1))>eps&×<500
bias(1)=error;
times=times+1;
% 计算聚类误差平方和
for i=1:K
temp=(M(i,:)-datas).^2;
dd=sqrt(sum(temp,2));
D(:,i)=dd;
end
% 初始化类别
Classify={};
% 将数据集中的数据分配给与其距离最近的中心点
[value_,class_]=min(D,[],2);
for h=1:K
index_=find(class_==h);
Classify{h}=datas(index_,:)
end
% 计算聚类误差平方和
temp_error=0;
for q=1:K
center_m=M(q,:);
temp1=Classify{q};
temp2=(center_m-temp1).^2;
ddd=sum(sqrt(sum(temp2,2)));
temp_error=temp_error+ddd;
end
% 更新聚类误差平方和
error=temp_error;
bias(2)=error;
% 找出不同类别的点
% 更新聚类中心
for m=1:K
temp=Classify{m};
nn=mean(temp);
M(m,:)=nn;
end
end