【问题标题】:Clustering points based on their function values and proximity基于函数值和邻近度的聚类点
【发布时间】:2017-01-22 07:39:12
【问题描述】:

我有很多点X 和它们的函数值f 存储在numpy 数组中。我想在X 中找到在r 距离内没有更好点(较小的f 值)的所有点

X 是数十万个点,所以我无法预先计算 sp.spatial.distance.pdist(X) 而是采用以下方法:

def cluster(X,f,r):
    pts,n = np.shape(X)
    centers = []
    for i in range(0,pts):
        pdist = sp.spatial.distance.cdist(X,[X[i]])
        if not np.any(np.logical_and(pdist <= r, f < f[i])):
            centers.append(i)
    return centers

这需要几分钟。有没有办法根据邻近度和其他指标快速聚类?

【问题讨论】:

  • 5.19 到 3.82 减少了 25%,这并不是说“没有那么快”。如果你能分摊分拣成本,那就更好了。

标签: python numpy scipy cluster-analysis


【解决方案1】:

您可以对空间进行分区,以便完全忽略被测试点半径之外的分区。

您也可以按 f 对点进行排序,因此您不需要扫描那些具有较小值的点。

【讨论】:

  • f 对点进行排序稍快一些。请参阅编辑 1。我希望有更快的速度,也许是通过向量化 cdist 计算而不需要全部存储。所有的点都在一个盒子里,所以看起来“划分空间”需要同样多的计算工作。
  • 你可以买更好的硬件:)
【解决方案2】:

我认为可以总结为:

使用k-最近邻构建kdtree。用半径查询靠近查询点的点的树,检查它们的函数值。

x=scipy.random.rand(10000,2) # sample data
f = exp(-x[:,0]**2) # sample function values
K=scipy.spatial.KDTree(x) # generate kdtree of data set
ix = K.query_point_ball(x[0],0.1) # query indices of points within 0.1 of x[0] in euclidean norm
# check f[ix] for your function criterion

有兴趣的可以一次性查询所有点

ix = K.query_point_ball(x,0.04)

【讨论】:

  • 这比原来的方法慢很多。请参阅编辑 2
【解决方案3】:

您可以通过记录来显着减少距离计算的次数。例如,如果 j 是中心 i 的邻居并且它具有较大的 f 值,那么 j 永远不可能是中心,因为它的邻居之一是具有较小 f 值的 i。请检查以下内容,如果您需要澄清,请告诉我。

def cluster4(X,f,r):
    pts,n = np.shape(X)
    centers = np.ones((pts,1),dtype=int)
    for i in range(pts):
        if not centers[i]:
            continue
        pdist = sp.spatial.distance.cdist(X,[X[i]])
        inrange = (pdist <= r)
        inrange[i] = False
        lesser = (f < f[i])
        if np.any(inrange & lesser):
            centers[i] = 0
        centers[inrange & np.invert(lesser)] = 0
    return np.where(centers == 1)[0]

【讨论】:

  • 用这种方法对 500,000 个点进行排序将计算时间从 28 秒的蛮力缩短到 0.06 秒!
猜你喜欢
  • 2015-10-06
  • 2019-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-23
  • 2011-12-06
  • 1970-01-01
  • 2011-10-22
相关资源
最近更新 更多