K-Means 的特点及改进

K-Means 是数字信号分析的入门级算法,其代码可读性极高,但是也有一两个小问题。

首先,起始点是随机选择,而且起始点的位置与最终的结果有极高的相关性,因此只能达到局部最优解。为了更加接近全局最优解,有人提出计算很多次,每次使用不同的随机起点,然后从中选择聚合度最高的解做为输出。这样做会导致两个问题,从理论上讲,局部最优解的多次重复和过滤只能产生次优解,没有办法达到最优解。

第二个问题就是在算法开始运行的时候就必须指定 K 值,我认为只能算特点,不能算弱点。当在高维空间运行的时候,我们很难事先通过 UI 获取图像,因此也就很难主观地确定 K 值。在这种场景里,肯定是一个很大的弱点。但在另一方面,有时我们本来就需要事先确定 K 值。例如,要从一系列的 T 恤的高宽尺寸中分离出 S、M 和 L 三种型的类。在此,确定 K 只能算是特点而不是弱点。

为此,我在分层算法的基础上,通过定义聚类的熵的方法,实现了一种无需指定 K 值的自动算法。

0. 将所有点的设为顶点(即 .isTop 属性设为 TRUE)。

1. 在当前的点阵计算所有点之间的距离,如果两点互为最近点,则生成一个文件夹将其放入。新文件夹设为顶点,同时将其包含的所有节点(包括文件夹和节点)设为非顶点。

只有顶点才计入当前点。

2 将同一个文件夹内的所有点(包括子文件夹包含的点)提取出来,计算其平均值,做为当前新文件夹的形心。

循环1和2,直到只有一个顶点时,即可退出。

这样就形成了一颗不完全二叉树,节点包括的内容有三种情况:节点与节点,节点与点,点与点。

在手工指定 K 的情况下,我们可以自上向下遍历,然后将当前结果集中的直径最大的子节点分割。直到当前分割数量 == K。

在自动算法中,分割方法与手动的情况相同,只需要定义一个收敛的开关即可:

设树的根为顶点C

运行:

{

        分割:将顶点C分割成它对应的两个子节点。

       遍历所有点,返回它与当前所有顶点的距离,如果距离它最近的顶点是它所在的集合的编号,则返回 TRUE。

       否则:返回与该点距离最近的集合,以及当前集合,在其中选择外切圆的直径较大的一个,设为顶点C。

       GOTO 分割;

}

当上一段代码运行结束时,与每一点距离最近的顶点均是它对应的群的形心。这就可以被认为是聚类的数量与聚集程度的平衡点。

K 值的变化导致的运算只局限于分割算法中,树是处于只读的状态。

无图无真相:

 图1.A

 图1.B

 图1.C

图X.A 为源数据以及相应的二叉树。这是一颗包括了位置信息的二叉树,它的层次数据很难读取,只能从连线的长度来大致判断。

图X.2 为自动算法返回的结果。

图X.3 为手动指定 K 的算法返回的结果。

因为两种算法中,决定哪一个顶点被展开的标准稍有不同,因此两个输出也稍有不同,但均可以高效地去除孤点。

 图2.A

 图2.B

 图2.C

图3.A

 图3.B

 图3.C

 图4.A

 图4.B

 图4.C

仔细观察,发现自动算法中的切分标准比指定 K 的算法要合理一点,类之间的混淆情况大幅度降低。事实上,我们可能通过定交不同的优先切割标准来得到 K 值相同时的不同结果。但总的来说,区别都不是太大。

这个算法的问题是刚开始建二叉树的时候复杂度太高,随着树叶的建立,运算量越来越少。到了后期切分的时候,基本上就没什么运算了,切分完成后,可需要确定每个点对应的分类下标即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值