当前位置: 代码网 > it编程>编程语言>C/C++ > matlab实现K-means聚类的动态过程

matlab实现K-means聚类的动态过程

2024年07月31日 C/C++ 我要评论
K-means聚类算法是一种简单实用的聚类算法,本文对K-means聚类算法进行了简单的介绍,并利用动态图的方式展现K-means聚类算法进行每一次迭代时的变化

 k-means聚类算法

1.1基本原理

  1. k-means聚类算法在1967年由j.b.macqueen提出,是一种基于划分的动态聚类算法,同时也是一种具有较大影响力的无监督学习算法。该算法是对一个n维向量的数据点集d={xi|i=1,···,n}进行聚类,其中xi表示第i个数据点,最终将集合d划分成k个类簇。分组的依据主要把越相似、差异越小的样本聚成一类(簇),最后形成多个簇,使同一个簇内部的样本相似度高,不同簇之间差异性高。

距离的度量有欧几里得距离、曼哈顿距离和切比雪夫距离,如下所示:

检验聚类结果的方法:

  1. 肘部法sse(sum of the squared errors,误差平方和),利用计算误方差和,来实现对不同k值的选取后,每个k值对应簇内的点到中心点的距离误差平方和,理论上sse的值越小,代表聚类效果越好,通过数据测试,sse的值会逐渐趋向一个最小值。

误差平方和sse计算公式 sse=

式中:ci为第i个类簇;c i为簇c i的聚类中心;x为 数据集d中的数据对象;k为类簇数目。

  1. 轮廓系数(silhouette coefficient),是聚类效果好坏的一种评价方式。最早由 peter j. rousseeuw 在 1986 提出。它结合内聚度和分离度两种因素。可以用来在相同原始数据的基础上用来评价不同算法、或者算法不同运行方式对聚类结果所产生的影响。

 a(i) :i向量到同一簇内其他点不相似程度的平均值

b(i) :i向量到其他簇的平均不相似程度的最小值

可见轮廓系数的值是介于 [-1,1] ,越趋近于1代表内聚度和分离度都相对较优。

1.2具体步骤

  1. 选择k个数据作初始聚类中心
  2. 分别计算所有数据点到各个初始聚类中心的距离,
  3. 将数据点就近分配到各个初始聚类中心所在的集合中形成一个簇。
  4. 根据簇中的各个点,更新每个簇的中心。(计算中心样本均值作为新的中心)
  5. 重复分配和更新的步骤,直到簇基本不再发生变化时,算法结束。

具体步骤程如图所示:

 2特点

2.1优点

  1. 原理比较简单,实现也是很容易,收敛速度快。
  2. 当结果簇是密集的,而簇与簇之间区别明显时, 它的效果较好。
  3. 主要需要调参的参数仅仅是簇数k。

2.2缺陷

  1. k值需要预先给定,很多情况下k值的估计是非常困难的。
  2. k-means算法对初始选取的中心点是敏感的,不同的随机种子点得到的聚类结果完全不同 ,对结果影响很大。
  3. 对于噪音和异常点比较敏感。
  4. 结果不一定是全局最优,只能保证局部最优。

3、matlab代码运行结果

4、部分代码 

clc;
clear all;
close all;
data(:,1)=rand(1,100)*300;%data的第一列在1-300间取100个数
data(:,2)=rand(1,100)*300;%data的第二列在1-300间取100个数
%% 用原理推导k-means算法
[m,n]=size(data);%判断data的行数m和列数n
k=3;%聚类数
center=data(randperm(m,k),:);%随机选择m行中的k个做为初始中心
maxgen=50;%最大迭代次数
lim=0.001;%中心变化阈值,当新产生的中心与前一个中心小于这个阈值时结束聚类
for i=1:maxgen
    for j=1:k
        distance=(data-repmat(center(j,:),m,1)).^2;%计算每个样本到选取中心的距离
        distance1(:,j)=sqrt(sum(distance'));%欧式距离
    end
        [~,indexk]=min(distance1');%找出每一行最小的所在的位置
        %新的中心位置分类后各样本均值
        for g=1:k
            newcenter(g,:)=mean(data(find(indexk==g),:));
        end
        %% 作图
        a=unique(indexk);%找出分类出的个数即k的值1 2 3
        c=cell(1,length(a));%加入元胞数组,1行a的长度为列
        %将同一数值的加入到同一元素内
        for t=1:length(a)
            c(1,t)={find(indexk==a(t))};
        end
        %对分好类的数据根据其范围填充相应颜色
        for j=1:k
            getdata=data(c{1,j},:);
            if j==1
                %大小100,颜色填充红/绿/蓝/黄/青,里面透明度0.5,边缘透明度0.7
            scatter(getdata(:,1),getdata(:,2),100,"markerfacecolor",[1 0 0],"markerfacealpha",0.5,"markeredgealpha",0.7);
            else if j==2
            scatter(getdata(:,1),getdata(:,2),100,"markerfacecolor",[0 1 0],"markerfacealpha",0.5,"markeredgealpha",0.7);     
                else if j==3
                        scatter(getdata(:,1),getdata(:,2),100,"markerfacecolor",[0 0 1],"markerfacealpha",0.5,"markeredgealpha",0.7);
                    else if j==4
                        scatter(getdata(:,1),getdata(:,2),100,"markerfacecolor",[1 1 0],"markerfacealpha",0.5,"markeredgealpha",0.7);
                        else
                         scatter(getdata(:,1),getdata(:,2),100,"markerfacecolor",[0 1 1],"markerfacealpha",0.5,"markeredgealpha",0.7);
                        end
                    end
                end
            end
            hold on
        end
        %给每个位置加上序号
        for f=1:max(size(data))
            h=num2str(f);
            text(data(f,1),data(f,2),h);
        end
         %中心点用黑色菱形表示
         plot(center(:,1),center(:,2),"kd","linewidth",2)
         %评价聚类好坏的指标
         sc=mean(silhouette(data,indexk'));
         title(['k-means聚类,聚数为:',num2str(k),'迭代次数:',num2str(i),' ,sc轮廓系数',num2str(sc)])
     %% 判断新的中心和原来的中心是否基本不变,小于阈值则算法结束,否则继续
        if (sqrt(sum((newcenter-center).^2))>lim)
           center=newcenter;
        else
            break;
        end
end  
center

原输入值取得随机数,每次所得结果不尽相同,可自行更换为需要的数据。

完整源码获得方式:微信或qq联系

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com