聚类分析笔记-K均值matlab算法(一)

一:介绍

关于聚类分析算法,类型较多,用法也不同。先收集一些网上的相关博客,有兴趣可以看看:

1.聚类分析综述:http://blog.csdn.net/assiduousknight/article/details/16831965

2.这个博主整了个聚类分析系列,很好呀,原理介绍部分棒,部分程序是用Java语言写的,熟悉的可以看看。

  贴其中一个索引:http://blog.csdn.net/zaozxueyuan/article/details/22613633

3.再收藏一个机器学习算法系列,当然里面有道关于K-均值算法。

     贴其中一个索引:http://blog.csdn.net/qq415171148/article/details/25394477

二:关于聚类分析的动态聚类算法

    下面的部分内容是看模式课程整理的:

2.1.思想: 一)选取K个样本作为聚类中心

          二)按某种聚类准则(如:最小距离准则)使所有样本点都找到自己所 属的初始类

         三)判断分类是否合理,不合理修改分类

     四)反复迭代修改直至分类合理

2.常用方法:

        ●  K-均值算法

        ●  ISODATA算法(迭代自组织数据分析算法)(matlab实现书籍上有)

              (有点复杂 --> 动态调整分类数目)

(这些算法,matlab都有自带的函数(还没用过!),当明白了算法的原理后,再去用这些函数应该很好)

2.2: K-均值算法   --->一般使用在已知可以分成几类的情况下效果好)

    思想:使聚类性能指标最小化,准则函数:每一个样本点到该类中心的 距离平方和 最小。

    算法:  一)选K个聚类中心,Z1)......ZK)。 开始可以任意选。

(任意选,选取的准确度与先验知识等等有关,可以考虑)

           二)逐个将需要分类的样本进行分类到K个初始类中的某一个 中,假设当i=j时,可以满足
, 那么x就属 于第Sj(k)个。

K:迭代次数,每个样本都得迭代K次才能判断出来那个是最近的。

Sj(k):第j个聚类,聚类中心为Z(j)

         三)计算各个聚类中心的新的值,组成新的聚类中心向量。

      

N:该类中样本的个数

有了聚类中心向量,可以使用聚类准则函数使函数值最小:

    

        (该步骤中要计算K个聚类的均值,所以叫K-均值)

比较: 若,则返回第二步继续迭代,所有 的模式样本重新分类。

(此时与上一回合变化的只是聚类中心点,这已经足够了)如果相等,那么很明显算法收敛了(没有改变了)。

讨论该算法:

    K-均值受那些因素的影响:

        ●  所选的聚类数目(最直接的影响,所以说比较适合于已知类 别的分类)

    ●  聚类中心的初始分布

             ●  样本几何性质(越高维数据,计算量越大)

    ●  读入样本次序 

    进一步讨论方法:

        ●  试验中如果不知道分类数,那么可以试探不同的K值和不同 的聚类中心(可以随机产生初始聚类中心)。

        ●  模式样本本身类之间的差距大时,收敛性较好。

三:简易的matlab程序实现

   根据上面的算法思路,编写matlab程序如下:

%--------------函数说明-------------
%-----简单的两类聚类分类问题
%---(模拟数据,已知类别数为2类,K-means在已知类别下使用较好)
%-----------------------------------
function mean = k_means_new
%%
%------------随机生成用于分类的10对坐标---
%--------------(必须具有一定的差异性)
for i=1:100
    x1(i) = rand()*5;      %人为保证差异性
    y1(i) = rand()*5;  
    x2(i) = rand()*5 + 3; %人为保证差异性
    y2(i) = rand()*5 + 3;
end
x = [x1,x2];
y = [y1,y2];
cities = [x;y];
% plot(cities(1,:),cities(2,:),'*');  %画出来
%%
%------------随机把其中两个点作为初始的聚类中心
num = size(cities,2);   %样本个数
m1 = round(rand()*num);    %随机选取两个当做初始聚类中心
m2 = round(rand()*num);
while m1==m2               %不能相同
    m2 = round(rand()*num);
end                
u1 = cities(:,m1);        
u2 = cities(:,m2);
u_old = [u1,u2];
u_new = [u2,u1];
%%
while u_old ~= u_new   %聚类中心没有变化时退出循环
    u_old = u_new ;    %更新聚类中心坐标
    for j=1:num      %对与每一个样本,找到对应的类
        dis1 = norm(cities(:,j)-u1);  %求距离,范数
        dis2 = norm(cities(:,j)-u2);
        if dis1>=dis2  c(j) = 2;    %比较距离,划分类
        else c(j) = 1;
        end
    end
    index1 = find(c==1);   %索引第一类
    index2 = find(c==2);   %...
    sum1 = sum(cities(:,index1),2);  %对第一类中的元素x,y分别求和
    sum2 = sum(cities(:,index2),2);  %...
    u1 = sum1/length(index1);      %对第一类平均,求取新的聚类中心
    u2 = sum2/length(index2);     %...
    u_new = [u1,u2];        %新的聚类中心向量
end
%%
hold on,plot(cities(1,index1),cities(2,index1),'*');  %画出来
hold on,plot(cities(1,index2),cities(2,index2),'+');  
hold on,plot(u1(1),u1(2),'o',u2(1),u2(2),'o');
mean = u_new;   

直接运行函数就可以了,改变一下程序第二行的数字参数,使得初始生成的点个数不同,从而测试下效果:

初始点10个:

 

初始点20个:

 

初始点50个:

 

初始点100个:

 

实验了多次,看着都很准,基本上没有分错类的,可以看到K-均值对已知分类的问题效果确实还行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值