邓恩指数是一种评估聚类的方法。值越高越好。它被计算为最小簇间距离(即任何两个簇质心之间的最小距离)除以最高簇内距离(即,任何簇中任何两点之间的最大距离)。
我有一个计算Dunn指数的代码片段:
def dunn_index(pf, cf):
"""
pf -- all data points
cf -- cluster centroids
"""
numerator = inf
for c in cf: # for each cluster
for t in cf: # for each cluster
if t is c: continue # if same cluster, ignore
numerator = min(numerator, distance(t, c)) # find distance between centroids
denominator = 0
for c in cf: # for each cluster
for p in pf: # for each point
if p.get_cluster() is not c: continue # if point not in cluster, ignore
for t in pf: # for each point
if t.get_cluster() is not c: continue # if point not in cluster, ignore
if t is p: continue # if same point, ignore
denominator = max(denominator, distance(t, p))
return numerator/denominator
字符串
问题是这是异常缓慢:对于由5000个示例和15个簇组成的示例数据集,上述函数最差需要执行刚好超过3.75亿次的距离计算。实际上,它要低得多,但即使是最好的情况下,数据已经按集群排序,也是大约2500万次距离计算。我想减少时间,我已经试过直线距离和欧几里得,这不是好事。
如何改进这个算法?
2条答案
按热度按时间zfciruhq1#
TLDR:重要的是,问题是在二维中建立的。对于大尺寸,这些技术可能是无效的。
在2D中,我们可以在
O(n log n)
时间内计算每个簇的直径(簇内距离),其中n
是使用凸包的簇大小。矢量化用于加速剩余操作。有两种可能的渐进改进在帖子的末尾提到,欢迎投稿;)设置和伪造数据:
字符串
看起来有点像这样:
x1c 0d1x的数据
接下来,我们定义了一个
diameter
函数,用于计算最大的集群内距离,基于这种方法使用船体。型
对于Dunn指数计算,我假设我们已经计算了点、聚类标签和聚类质心。
如果集群数量较大,则以下基于Pandas的解决方案可能会表现良好:
型
否则,我们可以继续使用纯
numpy
解。型
对于
1000
集群大小为i.i.d. ~U[1,1000]
的1000
集群,这需要2.2。秒在我的机器上对于本例(许多小集群),使用Pandas方法,这个数字下降到0.8秒。当集群数量较大时,还有两个相关的进一步优化机会:
O(k^2)
方法计算最小集群间距离,其中k
是集群的数量。这可以减少到O(k log(k))
,如所讨论的here。max(diameter(pts[labels==i]) for i in np.unique(labels))
需要k
遍历大小为n
的数组。对于许多集群,这可能成为瓶颈(如本例所示)。使用pandas方法可以减轻这一点,但我希望可以进一步优化这一点。对于当前的参数,大约三分之一的计算时间花费在计算集群内距离的交换器之外。9wbgstp72#
这不是关于优化算法本身,但我认为以下建议之一可以提高性能。
1.使用multiprocessing的工作池。
1.将python代码提取为c/cpp。参见official documentation。
https://www.python.org上还有Performance Tips。