data=xlsread('D:\matlab\data.xlsx')
[N, d] = size(data);
% init U
sampleIds = randsample(1:N, 4, false) %从n个点中随机选择三个点作为中心点
U = data(sampleIds, 1:3); %以这三个点为中心形成簇类
labels_u = zeros(N, 1); %初始化建立一个N行1列的零数组
stop = true;
while stop %把true复制给stop,需要一直循环
for i = 1:N %从第1个点一直到第n个点
x = data(i, 1:3); %读取第1个数据放到X里面
% check label
label = 0; %初始化label为0,代表是第几个簇类
dist = 0; %初始化dist距离为0
for j = 1:4 %计算到达四个中心点的距离,依次推断属于哪个簇类
tmp_dist = sum((x-U(j, :)).^2);
if label == 0 || tmp_dist < dist
label = j;
dist = tmp_dist; %欧式距离更新为当前的更小值
end
end %循环结束
if labels_u(i) ~= label %如果第个i点不等于label
stop = false; %继续循环
end
labels_u(i) = label; %第个i点属于第label个簇类
end
if stop == true %退出循环
break;
end
%update U %更新中心点
new_U = zeros(4, d); %初始化中心点,并全部清零
labels_count = zeros(4, 1); %统计不同簇类的个数
for i = 1:N %遍历所有点
label = labels_u(i); %提取出簇类标志
new_U(label, :) = new_U(label, :) + data(i, :);
labels_count(label) = labels_count(label) + 1;
end
for j = 1:4%
new_U(j, :) = new_U(j, :)/labels_count(j); %初始化的中心点除以每个聚类里面总的个数
end
U = new_U; %用新的U来代替
E_in = 0;
for i = 1:N %N个点需要重新遍历
label = labels_u(i); %将label标签提取出来
u = U(label, :);
E_in = E_in + norm(data(i)-u);
end
E_in = E_in/N;
color=['r','g','b','y'];
figure
for i=1:4
plot3(data(labels_u==i,1),data(labels_u==i,2),data(labels_u==i,3),'color',color(i),'linestyle','none','marker','x')
hold on
end
axis equal
最后的结果:
我们发现k-mean均值算法对是基于样本和簇中心之间的距离进行分类的聚类算法,他的聚类结果是偏向于球状的簇,因此对于球状簇比较适合求解出合适的分类效果,而当数据集变为非球状结构的数据集合,他并不能达到很好的理想聚类效果,因此,DBSCAN没准是一个处理非球状数据的良好解决办法,可能会具有较好的通用性。
作者邮箱是1171137119@qq.com 需要点云数据可以加我qq好友。