初探K-means聚类算法

K-means聚类算法到底是什么?

K-means算法实际上就是将目标数据集划分为k个样本空间,最后使得每个样本空间的点到其空间中心点的距离最小


K-means聚类算法中的距离

我们稍微深入思考一下上面那段话便可以得到一个疑问,k-means算法中描述样本之间距离的定义到底是什么?

我们该如何度量这个距离呢?在这里我们引入明可夫斯基(Minkowski)距离.

明可夫斯基(Minkowski)距离是基于曼哈顿距离欧几里得距离的一种推广

假设我们有两个点

                                                                  P_1=(x_1,x_2,...,x_n);

                                                                  P_2=(y_1,y_2,...,y_n);

那么他们之间                              

                                                             dis_{Minkowski}=(\sum\limits_{n=1}^N{|x_i-y_i|^k})^\frac{1}{k}$

显然我们可以发现当k==1

                                                            dis_{Minkowski}=dis_{Manhattan}

k==2

                                                            dis_{Minkowski}=dis_{Euclidean}

 

有了如上对于距离的度量,我们应该很容易就能描述出该算法。

但是,要想描述各个样本子空间的dis属性,我们还需要一个东西--------样本子空间的聚类中心。


但是令人困扰的是,选取得到理论上总体最优的聚类中心是一个NP hard问题

不了解的可以戳右边的链接NP hard问题

虽然我们难以找到多项时间内能够解决该问题的算法,但是好在在现实应用中我们往往并不需要达到总体最优解,

很多时候我们只要能够迅速的得到局部最优解便能解决很多问题!

 

说到这里我们不得不提一下启发式算法,很多时候许多看似困难的问题都能够通过启发式(搜索)算法解决

例如ACM竞赛中我们常用的dsu on tree,也就是树上启发式合并

启发式算法的本质我个人是这样理解的:启发式的核心思想就是顺着自己合理的推断和猜想构造算法模型

听起来有点扯,但实际上这种略带随机感的算法模型往往能够带来意想不到的高效解答和优秀数据构造,

例如大家常说的模拟退火算法

 

在K-means算法的实现中,我们通过前期的测试可以发现初始的聚类中心的选择对最后聚类结果的影响很小

甚至可以说肉眼根本无法发掘他们细微的差别

因此可以默认牺牲一部分时间迭代以生成理想的聚类中心


如何迭代生成较为理想的聚类中心?

在这里由于博主是初学者,仅介绍一种效率相对比较低,但对初学者来说相对比较容易理解的构造方式

①随机选取(其实默认手动输入也行)k个初始聚类中心

②计算每个样本点到聚类中心的距离

③根据到聚类中心的距离划分出k个样本子空间

④计算每个样本子空间的样本的中心点

⑤重复上述步骤迭代,直至新生成的聚类中心与上一次确定的聚类中心的误差<=eps


有了如上的基础之后,如果我们不考虑相对高效但较为复杂的聚类中心搜索,直接通过多次迭代选取合适的聚类中心便很容易实现k-means算法

tic
img=imread('C:\Users\Murphyc\Desktop\Pattern Recognition\Peppers.bmp');
img=double(img);
eps=0.00001
for i=1:200
    c1(1)=0;
    c2(1)=75;
    c3(1)=150;
    c4(1)=255;
    dis1=abs(img-c1(i));
    dis2=abs(img-c2(i));
    dis3=abs(img-c3(i));
    dis4=abs(img-c4(i));
    sub1=dis1-dis2;
    sub2=dis2-dis3;
    sub3=dis3-dis4;
    sub4=dis1-dis4;
    cf1=find(sub1<=0&sub4<=0);
    cf2=find(sub1>0&sub2<=0);
    cf3=find(sub2>0&sub3<=0);
    cf4=find(sub3>0&sub4>0);
    c1(i+1)=sum(img(cf1))/length(cf1);
    c2(i+1)=sum(img(cf2))/length(cf2);
    c3(i+1)=sum(img(cf3))/length(cf3);
    c4(i+1)=sum(img(cf4))/length(cf4);
    d1(i+1)=abs(c1(i+1)-c1(i));
    d2(i+1)=abs(c2(i+1)-c2(i));
    d3(i+1)=abs(c3(i+1)-c3(i));
    d4(i+1)=abs(c4(i+1)-c4(i));
    if d1(i+1)<=eps&&d2(i+1)<=eps&&d3(i+1)<=eps&&d4(i+1)<=eps
        cen1=c1(i+1);
        cen2=c2(i+1);
        cen3=c3(i+1);
        cen4=c4(i+1);
        break;
    end
end
img=uint8(img);
img(find(img<cen1))=0;
img(find(img>cen1&img<cen2))=64;
img(find(img>cen2&img<cen3))=128;
img(find(img>cen3&img<cen4))=192;
img(find(img>cen4))=255;
toc

接下来我们看下上面所示的代码的运行结果与效率

我们的输入数据为一个标准灰度图

 

最初他的灰度直方图是这样的

 

 

上述代码 在

                                                           

时间内便得到了较为理想的聚类结果

接下来我们观察一下聚类分割后的图像

直接看图像分割图似乎不太直观,那么我们接着看看现在的图像灰度直方图 

上图非常直观的可以看出经过多次迭代后我们得到了四个聚类结果十分理想的聚类点,具体是哪四个呢?

我们可以直接看看matlab工作区的数据

可见该图像关于上述的cen_1,cen_2,cen_3,cen_4能够得到较为理想的聚类分割结果。


小结

 

虽然k-means算法对于费离散的簇团数据集的分割效果很好,但是由于他的核心思想仍旧是比较简单的贪心思想,对于梭形的数据集或者是孤立点较多且离散的数据集,k-means算法得到的分割子空间便不会那么理想,可见该算法朴素模型下的局限型仍旧是很大的。

 

K-means算法还有一个很重要的部分即为k的选取,这部分接下来在寒假有空会继续介绍一些可以求解的优秀的算法模型.

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值