基于BinaryVector优化的KModes算法

来源:互联网 发布:千万不要在淘宝上搜索 编辑:程序博客网 时间:2024/05/29 04:57

这里将记录一下,如何快速的开发一个针对binary vector进行优化的KModes聚类算法。

首先,KModes算法本身和KMeans的过程是一致的,差别在于distance function和质心的更新方法上。

KModes采用Hamming Distance计算向量间的距离,质心的更新方法则是统计每个column中,出现频数最多的类别。
假设一共有5个向量:
[0, 1, 1, 0, 0]
[0, 0, 0, 1, 1]
[0, 0, 0 1, 0]
[1, 1, 1, 0, 0]
[1, 1, 0, 0, 0]
可以看到1,4,5是一类,2,3是一类。
更新的时候,假设1,2,3被划分到了一起,那么他们的质心计算过程就是:

  • 统计每个column的值分布,[ {0:3, 1:0}, {0:2, 1:1}, {0:2, 1:1}, {0:1, 1:2}, {0:2, 1:1} ]
  • 每个column下都保留最大值,[0, 0, 0, 1, 0]

接下来谈谈如何优化,binary vector一个重要的优化点就是数据表征,比如一个16维的0,1数组,可以用两个uint8_t的整数来压缩表示:

In: import numpy as npIn: np.packbits([0, 0, 0, 1, 1, 0, 1, 0,   1, 0, 0, 0, 1, 0, 1, 1])Out: array([ 26, 139], dtype=uint8)

那么两个向量间的汉明距离,实际上就是压缩后的向量间,每一个column的汉明距离的总和。
即,[0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1]和[0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]的汉明距离等价于[ 26, 139]和[ 26, 138]的汉明距离总和。
两个整型数字的汉明距离可以先按位xor(异或),再使用popcount计算位为1的数量。

# uint8_t的popcount算法x = (x & 0x55) + (x >> 1 & 0x55)x = (x & 0x33) + (x >> 2 & 0x33)x = (x & 0x0f) + (x >> 4 & 0x0f)

真正的问题在于如何高效的计算划分到某个质心的值分布。
我们需要将压缩后的向量解压缩成标准的0,1数组,才能进行计算,但因为我们用的是uint8大小的整型数字对向量进行表征,所以我们可以快速的通过一个256*8的二维数组,对某个压缩后的数字进行对应的0,1数组的查找。
即,可以通过

In: u8tb = np.unpackbits(np.arange(256, dtype=np.uint8).reshape(-1, 1), axis=-1)In: u8tb[26]Out: array([0, 0, 0, 1, 1, 0, 1, 0], dtype=uint8)

快速的找到26对应的数组[0,0,0,1,1,0,1,0]。

这样一来,基于binary vector的计算优化就基本完成了,具体可以看github上的项目代码。

原创粉丝点击