聚类结构3D数据

时间:2014-03-14 09:25:52

标签: python cluster-analysis

假设我有许多物体(类似于蛋白质,但不完全相同),每个物体都由n个3D坐标的矢量表示。这些对象中的每一个都定位在空间的某个地方。它们的相似性可以通过使用Kabsch Algorithm对齐它们并计算对齐坐标的均方根偏差来计算。

我的问题是,以这种方式聚类大量这些结构的推荐方法是什么,以便提取人口最多的聚类(即大多数结构所属的聚类)。另外,有没有办法在python中执行此操作。举例来说,这是一组平凡的非聚集结构(每个都由四个顶点的坐标表示):

enter image description here

然后是所需的聚类(使用两个聚类):

enter image description here

我尝试将所有结构与参考结构(即第一个结构)对齐,然后使用Pycluster.kcluster对参考坐标和对齐坐标之间的距离执行k-means,但这似乎有点笨拙而且效果不好。每个群集中的结构最终并不是非常相似。理想情况下,这种聚类不会对差异向量进行,而是对实际结构本身进行,但结构具有维度(n,3)而不是k均值聚类所需的(n,)。

我尝试的另一个选项是scipy.clustering.hierarchical。这似乎工作得很好,但是我无法确定哪个群集是最常填充的,因为通过向上移动到树的下一个分支,总能找到更多填充的群集。

非常感谢任何有关不同(已在python中实现)聚类算法的想法或建议或想法。

1 个答案:

答案 0 :(得分:1)

为了对我自己的问题作一个介绍性的答案,我建议人们可以使用形状中每个点之间的距离列表作为执行聚类的度量。

让我们创造一些形状:

shapes = np.array([[[1,4],[4,2],[11,2],[14,0]],
          [[4,5],[4,2],[11,2],[13,0]],
          [[1,3],[4,2],[11,2],[14,1.5]],
          [[3,5],[4,2],[10,7],[7,9]],
          [[5,5],[4,2],[10,7],[6,6]]])

def random_rotation():
    theta = 3 * np.pi * np.random.random()
    rotMatrix = numpy.array([[np.cos(theta), -np.sin(theta)], 
                             [np.sin(theta),  np.cos(theta)]])
    return rotMatrix

new_shapes = []
for s in shapes:
    rr = random_rotation()
    new_shapes += [[list(rr.dot(p)) + [0] for p in s]]
new_shapes = np.array(new_shapes)

for i, s in enumerate(new_shapes):
    plot(s[:,0], s[:,1], color='black')
    text(np.mean(s[:,0]), np.mean(s[:,1]), str(i), fontsize=14)

enter image description here

然后我们创建一些辅助函数并创建一个包含每个形状(darray)的所有顶点间距离的数组。

import itertools as it

def vec_distance(v1, v2):
    '''
    The distance between two vectors.
    '''
    diff = v2 - v1
    return math.sqrt(sum(diff * diff))

def distances(s):
    '''
    Compute the distance array for a shape s.
    '''
    ds = [vec_distance(p1, p2) for p1,p2 in it.combinations(s, r=2)]

    return np.array(ds)


# create an array of inter-shape distances for each shape
darray = np.array([distances(s) for s in new_shapes])

使用Pycluster将它们集中到两个群集中。

import Pycluster as pc

clust = pc.kcluster(darray,2)
print clust

看到我们最终在第一个集群中有三个条目,在另一个集群中有两个。

(array([0, 0, 0, 1, 1], dtype=int32), 4.576996142441375, 1)

但它们对应哪种形状?

import brewer2mpl

dark2 = brewer2mpl.get_map('Dark2', 'qualitative', 4).mpl_colors

for i,(s,c) in enumerate(zip(new_shapes, clust[0])):
    plot(s[:,0], s[:,1], color=dark2[c])
    text(np.mean(s[:,0]), np.mean(s[:,1]), str(i), fontsize=14)

Clustered Shapes

看起来不错!问题是随着形状变大,距离数组相对于顶点数以二次时间增长。我找到了一个描述这个问题的presentation,并提出了一些解决方案(比如SVD,我认为这是一种降维方式)来加快速度。

我还没有接受我的回答,因为我对如何处理这个简单问题的任何其他想法或想法感兴趣。