【代码】K-means聚类详解及实现 (Matlab聚类工具箱和自己实现)

首先给大家推荐一下我老师大神的人工智能教学网站。教学不仅零基础,通俗易懂,而且非常风趣幽默,还时不时有内涵黄段子!点这里可以跳转到网站

一. 聚类

先说说聚类。顾名思义,就是有一团数据,根据某种准则把相似的数据分别聚在一起,形成不同的类别(每个类别称为一簇)。聚类是一种无监督的算法。所谓无监督就是说,虽然聚类把物体分类到了不同的簇,只能知道哪些数据是属于同一类的,至于这一类数据到底是什么,并不知道。

聚类分为原型聚类、系统聚类、密度聚类。

原型聚类:先找几个原型(随机找k个元素作为k个类的中心),其他元素加入到距离最近的类里去,再次计算中心,根据距离重新分类,至中心不变为止。

系统聚类:每个元素各成一类,然后根据类间的距离,合并距离最小的,直至一类。

密度聚类:(等学了再补充)

对于距离:

样本之间常采用闵科夫斯基距离(minkowski),欧式距离等。

类间的距离有最短距离(single)、最长距离(complex)、中间距离(median)、重心距离(centriod)、平均距离(average)、离差平方和距离(ward)等。

聚类效果评价  (https://cn.mathworks.com/help/stats/cluster-evaluation.html matlab提供了相关函数包,相关准则参考matlab的工具箱支持)


1. Calinski Harabasz Evaluation[1]
2.Davies Bouldin Criterion [2]
3.Gap Value [3]
4. Silhouette criterion [4]

二. K-means

下面这篇文章写的挺好的,可以参考。

http://blog.csdn.net/mingtian715/article/details/51534165

三.代码

下面放一段自己写的matlab代码,不使用for循环,适合大量数据处理。复刻了周志华机器学习204页k-means给西瓜分类的结果。

%2017/10/27 K-means
%ref. 周志华 西瓜分类
clc;
clear;
close all;




data = [0.697 0.460;0.774,0.376;0.634,0.264;0.608,0.318;0.556,0.215;0.403,0.237;
        0.481,0.149;0.437,0.211;0.666,0.091;0.243,0.267;0.245,0.057;0.343,0.099;
        0.639 0.161;0.657,0.198;0.360,0.370;0.593,0.042;0.719,0.103;0.359,0.188;
        0.339,0.241;0.282,0.257;0.748,0.232;0.714,0.346;0.483,0.312;0.478,0.437;
        0.525,0.369;0.751,0.489;0.532,0.472;0.473,0.376;0.725,0.445;0.446,0.459;]
%聚类 数值初始化
% scatter(data(:,1),data(:,2))
% axis([0.1 0.9 0 0.8])
num = length(data);    %样本数
fea_n=2; %特征数
k = 3;  %簇数


%如果各特征数值差异较大,需要归一化
% maxd = max(data,2);
% data(:,1:fea_n)=data(:,1:fea_n)./repmat(maxd(1,1:fea_n),num,1);
% totalMean = mean(data(:,1:fea_n));


%产生不相等随机数
% b = randperm(num);
% r = b(1:k);


r = [6 12 24];%书中随机选取的初始化质心


%初始均值向量 u 1行 * k*fea_n列
u = [data(r(1,1),1:fea_n)];
for n = 2:k
    u = [u , data(r(1,n),1:fea_n)];
end


count = 1;%迭代次数
flag = 1;
cellshape([1:k],1) = fea_n;


while(flag&count<=4)
    
    if count == 1 %第迭代循环初始化
        old_u = u;
    end
    
    difer = (repmat(data(:,1:fea_n),1,k) - repmat(old_u,num,1)); 
    cell = mat2cell((difer.*difer),[num],cellshape); %按簇划分子块
    distcell = cell2mat(cellfun(@(x) sum(x,2).^0.5, cell,'UniformOutput',false)'); %计算距离
    dist=reshape(distcell,[],k);
    [mini,lambda] = min(dist,[],2);     %找到最近似的矩阵
    data = [data(:,1:fea_n),lambda]; %标记数据
    data = sortrows(data,3);


%各簇内记录的数量
    for n = 1:k
        len(1,n) = length(find(lambda==n));
    end
    
    datacell = mat2cell(data(:,1:fea_n)',[fea_n],len);
    new_u = cell2mat(cellfun(@(x) mean(x,2),datacell,'UniformOutput',false)')';
    flag = length(find(new_u-old_u~=0)); 
    old_u = new_u;
    count=count+1;
end


%画出分类结果
 Color_map = hsv(k);
 Label = data(:,fea_n+1);
 Color_Label = Color_map(Label,:);
 
 figure(1),clf
 C=reshape(new_u',2,[])';
 plot(C(:,1),C(:,2),'kx','MarkerSize',10,'LineWidth',3)
 hold on;
 scatter(data(:,1),data(:,2),40,Color_Label,'filled')
 xlabel('密度')
 ylabel('含糖率')
 title('第四轮迭代后')

四.结果、

五.聚类效果评价

用matlab自带的工具箱进行聚类效果分析,

rng('default');  % For reproducibilityeva = evalclusters(data,'kmeans','CalinskiHarabasz','KList',[1:10])plot(eva)

评价结果

eva = 


  CalinskiHarabaszEvaluation (带属性):


    NumObservations: 30
         InspectedK: [1 2 3 4 5 6 7 8 9 10]
    CriterionValues: [NaN 22.9791 28.0930 35.4862 33.0436 32.7692 29.9349 33.5191 32.8026 34.0822]
           OptimalK: 4

k=4是比较合适的,根据CH指标越大越好的准则,k=4有最好的结果。

引用

[1] Calinski, T., and J. Harabasz. “A dendrite method for cluster analysis.” Communications in Statistics. Vol. 3, No. 1, 1974, pp. 1–27.

[2] Davies, D. L., and D. W. Bouldin. “A Cluster Separation Measure.” IEEE Transactions on Pattern Analysis and Machine Intelligence. Vol. PAMI-1, No. 2, 1979, pp. 224–227.

[3] Tibshirani, R., G. Walther, and T. Hastie. “Estimating the number of clusters in a data set via the gap statistic.” Journal of the Royal Statistical Society: Series B. Vol. 63, Part 2, 2001, pp. 411–423.

点这里可以跳转到人工智能网站