因此,今天早上我了解到Minkowski指标并不总是意味着。

python - Scipy聚类;使用物理Minkowski度量?-LMLPHP
有关详细信息,请参见wolfram

显然,这只是个p范数。 Scipy可以选择对p范数进行加权,但只能使用正加权,因此无法实现相对论的Minkowski度量。

我想对相对论4维空间中的点进行分层聚类。有两点;

a = [a_time, a_x, a_y, a_z]

b = [b_time, b_x, b_y, b_z]

它们之间的距离应该是;

invarient_s(a, b) = sqrt(-(a_time-b_time)^2 + (a_x-b_x)^2 + (a_y-b_y)^2 + (a_z-b_z)^2)

我在python中工作,理想情况下使用scipy的fcluster。在我开始编写自己的集群之前,是否有将其用于fcluster的指标?我可以添加到可用指标列表吗?

编辑;似乎只有fclusterdata首先支持指标。

最佳答案

坏消息是,确实内置指标(尤其是一个名为Minkowski的指标)不支持负权重。我怀疑其原因是,在适当的度量标准中,只有且仅当d(x,y) = 0时才可以具有x = y,这是Minkowski度量标准所违反的。这可能是scipy中任何加权度量标准均不支持负权重的原因,另请参见this github thread中的注释。

好消息是scipy.cluster.hierarchy.fclusterdata的文档存在错误(now fixed in master),因为它声称

metric: str, optional

    The distance metric for calculating pairwise distances.
    See distance.pdist for descriptions and linkage to verify
    compatibility with the linkage method.


实际的implementation of fclusterdata只是将metric输入参数传递给pdist,这允许将自定义可调用对象作为metric传递:

metric: str or function, optional


当然,我们可以定义自己的Minkowski度量函数并将其传递给fclusterdata,但是我们必须确保所有点在空间上都是分开的,否则我们会得到复杂的距离,并且pdist会大声失败(抱怨“有限”数据,因为np.sqrt当给出负数时将返回nan,并且nan无法通过np.isfinite中的linkage校验)。通过这种合理的警告,类似以下内容的工作:

from scipy.cluster.hierarchy import fclusterdata
from numpy.random import default_rng  # only for dummy data

# generate random data, use new random machinery for best practices
N = 10
rng = default_rng()
X = rng.random((N, 4)) * [0.01, 1, 1, 1]  # make them all space-like

def physical_minkowski(v1, v2):
    """Return the proper Minkowski metric for 4-vectors with signature -+++"""
    return np.sqrt(([-1, 1, 1, 1] * v1).dot(v2))

fclusterdata(X, t=1, metric=physical_minkowski)
# returns uninteresting array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)


由于上面的函数可能会被调用很多次,因此使用numba.njit对其进行编译以提高性能可能是有意义的。只需进行很小的更改就可以实现:

import numba

@numba.njit
def jitted_minkowski(v1, v2):
    return np.sqrt((np.array([-1, 1, 1, 1]) * v1).dot(v2))


我使用IPython的内置%timeit魔术和N = 1000为上述两个度量函数计时,以进行合理的比较:

>>> %timeit scipy.spatial.distance.pdist(X, metric=physical_minkowski)
... %timeit scipy.spatial.distance.pdist(X, metric=jitted_minkowski)
2.2 s ± 90.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
385 ms ± 12.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)


这意味着对于较大的4个向量集,JIT编译的版本要快5倍,并且编译只需执行一次(您甚至可以将编译后的函数缓存在磁盘上,这样就不必每次都编译它了。您运行脚本)。

关于python - Scipy聚类;使用物理Minkowski度量?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59577418/

10-12 23:17