【发布时间】:2019-06-29 19:02:09
【问题描述】:
我想测量多维空间中两个分布之间的距离。
例如,我想在多个维度上进行诸如 Wasserstein 分布或能量距离之类的测量,而不是一维比较。
我找到了一维的包裹,但我仍然找到了多维的包裹。 我怎样才能摆脱困境?
【问题讨论】:
标签: python scipy distance distribution
我想测量多维空间中两个分布之间的距离。
例如,我想在多个维度上进行诸如 Wasserstein 分布或能量距离之类的测量,而不是一维比较。
我找到了一维的包裹,但我仍然找到了多维的包裹。 我怎样才能摆脱困境?
【问题讨论】:
标签: python scipy distance distribution
您可以分别使用 geomloss 或 dcor 包来更一般地实现 Wasserstein 和能量距离。 geomloss 还提供了范围广泛的其他距离,例如 hausdorff、能量、高斯和拉普拉斯距离。它还根据输入数据的大小使用不同的后端,默认使用基于pytorch的张量框架。
dcor 主要使用scipy.spatial.distance.pdist 和scipy.spatial.distance.cdist 来计算能量距离。
以下是 1D、2D 和 3D 距离计算的几个示例:
# create random 3D data for the test
import torch
torch.random.manual_seed(0)
X = torch.rand((3,100))
Y = torch.rand((3,100))
# energy distance with geomloss
from geomloss import SamplesLoss
Loss = SamplesLoss("energy")
# 3D tensors
Loss( X, Y ).item()
>>> 0.0063512325286865234
# 2D tensors
Loss( X[:,0:2], Y[:,0:2] ).item()
>>> 0.005196928977966309
# 1D tensors
Loss( X[:,0,np.newaxis], Y[:,0,np.newaxis] ).item()
>>> 0.004647582769393921
# energy distance with dcor
import dcor
# 3D tensors
dcor.energy_distance(X,Y)/2
>>> 0.006351688367976838
# 2D tensors
dcor.energy_distance(X[:,0:2], Y[:,0:2])/2
>>> 0.005197086538981377
# 1D tensors
dcor.energy_distance(X[:,0,np.newaxis], Y[:,0,np.newaxis])/2
>>> 0.004647575813531868
您可能已经注意到,我将能量距离除以二。这是因为geomloss 计算能量距离除以二,我想比较两个包之间的结果。
你也可以看看my implementation的能量距离是兼容不同输入维度的。它是使用 Numba 编写的,它可以并行化计算并使用可用的硬件提升,原则上应该可以在 GPU 上运行它,但我还没有尝试过。尽管它的执行速度比dcor 实现要慢。
使用更多参数计算 Wasserstein 距离有点进化。 Sinkhorn 距离是 Wasserstein 距离的正则化版本,程序包使用它来近似 Wasserstein 距离。它也可以看作是 Wasserstein 和能量距离之间的插值,更多信息请参见 this paper。原则上,对于接近于零的小模糊值,您会期望得到 Wasserstein,而对于较大的值,您会得到能量距离,但由于某些原因(我认为由于一些实现问题和数值/精度问题)在一些较大的值之后,你会得到一些负值的距离。无论如何,如果您对 Wasserstein 距离感兴趣,这里有一个示例:
Loss = SamplesLoss("sinkhorn", blur=0.05,)
Loss( X, Y ).item()
>>> 0.01524302177131176
Loss( X[:,0:2], Y[:,0:2] ).item()
>>> 0.005164701491594315
Loss( X[:,0,np.newaxis], Y[:,0,np.newaxis] ).item()
>>> 0.0018786040600389242
除了blur,我建议查看此方法的其他参数,例如p、scaling 和debias。请注意,此方法的实现与 scipy.stats.wasserstein_distance 略有不同,您可能需要先查看文档或代码中的定义,然后再对 1D 情况进行两者之间的比较!
【讨论】:
我想你还是想测量两个分布之间的距离?即使您的数据是多维的,您也可以通过展平数组flat_array1 = array1.flatten() 和flat_array2 = array2.flatten() 来导出每个数组的分布,测量每个数组的分布(我的代码用于累积分布,但您也可以使用高斯分布)- 我正在做我的功能在这里变平:
`def ecdf(data):
'''compute eCDF of an image'''
data_flatten = data.flatten()
sort_data = np.sort(data_flatten)
values, bins = np.histogram(sort_data, normed=True)
cum_data = np.cumsum(values)
return (bins, cum_data)`
然后测量两个分布之间的距离。
假设您有两个 3D 数组并且您想测量相似度(或相异度,即距离),您可以使用上述函数检索分布,然后使用熵、Kullback Liebler 或 Wasserstein 距离。
【讨论】: