聚类算法是给一大堆原始数据,然后通过算法将其中具有相似特征的数据聚为一类。
k-means聚类,也叫k均值聚类,要先给出原始数据所含的类数,然后将含有相似特征的数据聚为一个类中。并不需要关心某一类是什么,我们需要实现的目标只是把相似的东西聚到一起,不需要使用训练数据进行学习,所以这属于无监督学习。
步骤一般如下:
1、从所以数据中随机取k个元素,作为k个类的各自的中心。
2、分别计算剩下的元素到k个类中心的相异度(常用欧式距离),将这些元素分别划归到相异度最低(即距离最近)的类。
3、根据聚类结果,找到每一类的所有数据,计算他们的平均值,作为下次计算的聚类中心。
4、将数据中全部元素按照新的中心重新聚类。
5、重复第4步,直到聚类结果不再变化。
6、将结果输出。
下面举个实例:
啤酒根据发酵方式分为三大类:
淡色啤酒,浓色啤酒,黑啤酒,其他啤酒对以下数据进行聚类
clear all
clc
data=[144.00 19.00 4.70 ;
181.00 19.00 4.90 ;
157.00 15.00 4.90 ;
170.00 7.00 5.20 ;
152.00 11.00 5.00 ;
145.00 23.00 4.60 ;
175.00 24.00 5.50 ;
149.00 27.00 4.70 ;
99.00 10.00 4.30 ;
113.00 6.00 3.70 ;
140.00 16.00 4.60 ;
102.00 15.00 4.10 ;
135.00 11.00 4.20 ;
150.00 19.00 4.70 ;
149.00 6.00 5.00 ;
68.00 15.00 2.30 ;
136.00 19.00 4.40 ;
144.00 24.00 4.90 ;
72.00 6.00 2.90 ;
97.00 7.00 4.20 ];
% data=[data1;data2;data3;data4];
[row,col] = size(data);
K = 4;
max_iter = 300;%%迭代次数
min_impro = 0.1;%%%%最小步长
display = 1;%%%判定条件
center = zeros(K,col);
U = zeros(K,col);
%% 初始化聚类中心
mi = zeros(col,1);
ma = zeros(col,1);
for i = 1:col
mi(i,1) = min(data(:,i));
ma(i,1) = max(data(:,i));
center(:,i) = ma(i,1) - (ma(i,1) - mi(i,1)) * rand(K,1);
end
%% 开始迭代
for o = 1:max_iter
%% 计算欧氏距离,用norm函数(即向量每个元素分别平方后求和再开方)
for i = 1:K
dist{i} = [];
for j = 1:row
dist{i} = [dist{i};data(j,:) - center(i,:)];
end
end
minDis = zeros(row,K);
for i = 1:row
tem = [];
for j = 1:K
tem = [tem norm(dist{j}(i,:))];
end
[nmin,index] = min(tem);
minDis(i,index) = norm(dist{index}(i,:));
end
%% 更新聚类中心
for i = 1:K
for j = 1:col
U(i,j) = sum(minDis(:,i).*data(:,j)) / sum(minDis(:,i));
end
end
%% 判定
if display
end
if o >1,
if max(abs(U - center)) < min_impro;
break;
else
center = U;
end
end
end
%% 返回所属的类别
class = [];
for i = 1:row
dist = [];
for j = 1:K
dist = [dist norm(data(i,:) - U(j,:))];
end
[nmin,index] = min(dist);
class = [class;data(i,:) index];
end
%% 显示最后结果
[m,n] = size(class);
figure;
title('聚类结果');
hold on;
for i=1:row
if class(i,end)==1
plot3(class(i,1),class(i,2),class(i,3),'ro');
elseif class(i,end)==2
plot3(class(i,1),class(i,2),class(i,3),'go');
elseif class(i,end) == 3
plot3(class(i,1),class(i,2),class(i,3),'bo');
end
end
grid on;
得到结果:
这20种啤酒分别属于类别1,2,1,2,1,1,2,1,3,4,1,3,4,1,1,3,1,1,3,3