我有10000个具有形状(32,32,3)的矩阵。我想在所有矩阵之间创建一个欧几里德距离矩阵。最后,它会像,
[0, d2, d3, d4, ...]
[d1, 0, d3, d4, ...]
[d1, d2, 0, d4, ...]
[d1, d2, d3, 0, ...]
如何以最快的方式制作它?我尝试了以下内容,但需要很长时间才能完成。
import numpy as np
dists = []
for a in range(len(X_test)):
dists.append([])
for b in range(len(X_test)):
dists[a].append(np.linalg.norm(X_test[a] - X_test[b]))
print dists
答案 0 :(得分:2)
您可以利用距离矩阵对称的事实将时间缩短一半,并且只使用
计算上三角形部分for b in range(a+1, len(X_test)):
第5行。
我没有看到任何其他明显的优化,同时保持问题完全相同,但似乎您正在使用三通道格式的32x32图像。那个3072维度!为什么不首先下采样到4x4,转换为HSL颜色空间,并且只保留Hue和Lightness以获得(4,4,2)"签名"对于每个图像。如果您的问题主要与形状有关,那么您也可以扔掉Hue,基本上可以使用黑白图像。
(4,4,2)只有32个维度,与(32,32,3)相比节省100。如果您确实想在(32,32,3)空间中进行完全比较,则只能在(4,4,2)空间中已经非常相似的图像上执行此操作。
答案 1 :(得分:2)
我问自己“这个pdist / cdist的东西是什么?”而不是问“给我演示Divakar”。 - 我读到了pdist
和norm
,我发现了以下代码
导入内容:
In [1]: import numpy as np
In [2]: from scipy.spatial.distance import pdist
生成随机样本,不一定与OP的样本一样大,并根据Divakar的建议对其进行重塑
In [3]: a = np.random.random((100,32,32,3))
In [4]: b = a.reshape((100,32*32*3))
使用IPython的magic
,让我们对这两种方法进行基准测试
In [5]: %%timeit
...: dists = []
...: for i in range(len(a)):
...: dists.append([])
...: for j in range(len(a)):
...: dists[i].append(np.linalg.norm(a[i] - a[j]))
128 ms ± 337 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [6]: %timeit pdist(b)
12.3 ms ± 252 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [7]: dists1 = []
...: for i in range(len(a)):
...: dists1.append([])
...: for j in range(len(a)):
...: dists1[i].append(np.linalg.norm(a[i] - a[j]))
In [8]: dists2 = pdist(b)
为了比较结果,我们必须意识到pdist
只计算距离方矩阵的上三角(因为矩阵是对称的,而主对角线同样等于零)所以我们必须小心在检查我们的结果时:因此我使用allclose
dists1
的第一行的非对角线部分以及dists2
的前99个元素
In [9]: np.allclose(dists1[0][1:], dists2[:99])
Out[9]: True
结果是一样的,很好。
估算10,000个元素所需的时间怎么样?感觉就是二次方,但让我们试验加倍元素的数量
In [10]: b = np.random.random((200,32*32*3))
In [11]: %timeit pdist(b)
48 ms ± 97.7 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [12]:
新的时间是初始时间的4倍,所以我的计算量,在我的微软电脑和使用Divakar的提议上的估计是12ms x 100 x 100 = 120,000ms = 120s。您应该the excellent answer仔细阅读olooney并确定您真正想做的事情。