Julia:跨观察张量广播成对距离计算
Julia: Broadcasting pairwise distance calculation across tensor of observations
我正在尝试使用 Julia 中的 Distances
包来执行距离矩阵的广播计算。
我了解如何计算某个矩阵 X
(维度 D x N
)的单个 N x N
距离矩阵,其中每一列 X[:,i]
存储一个 D
维特征向量进行观察i
。代码将是:
using Distances
dist_matrix = pairwise(Euclidean(), X, dims = 2)
dist_matrix
包含每对 D
维列之间的欧氏距离,例如dist_matrix[m,n]
存储 X[:,m]
和 X[:,n]
之间的欧氏距离。
现在假设我的数组 X
实际上是 张量 或 'volume' 的 D
维观测值,因此 X[:,i,j]
存储我的 D x N
个观察结果中的第 j
个 'slice'。整个数组 X
因此具有维度 D x N x T
,其中 T
是切片的数量。
因此,我想计算距离矩阵的 张量 或 'volume',因此 dist_matrix
的维度为 N x N x T
。
有没有办法通过在 Julia 中广播 pairwise()
函数在一行中完成此操作?最快的方法是什么?下面显示了带有基本 for 循环的想法:
using Distances
dist_matrix_tensor = zeros(N,N,T);
for t = 1:T
dist_matrix_tensor[:,:,t] = pairwise(Euclidean(), X[:,:,t], dims = 2)
end
编辑:
我想出了如何使用 mapslices
来做到这一点,但仍然不确定这是否是最好的方法。
using Distances
dist_function(x) = pairwise(Euclidean(), x, dims = 2) # define a function that gets the N x N distance matrix for a single 'slice'
dist_matrix_tensor = mapslices(dist_function, X, dims = [1,2]) # map your matrix-operating function across the slices of the main tensor X
这当然也可以并行化,因为 X 的每个 'slice' 在此计算中都是独立的,所以我基本上只是在寻找最快的方法来执行此操作。总的来说,我也对您如何通过广播来做到这一点很感兴趣。
如果 X
的维度很大,您使用 mapslices
的解决方案的性能相当不错。下面是一个使用 JuliennedArrays 的例子,它对于小 X
稍微快一点,但是当前两个维度的大小为 100 时,它与 mapslices
具有相同的性能。
using Distances, JuliennedArrays, BenchmarkTools
dist_function(x) = pairwise(Euclidean(), x, dims = 2) # define a function that gets the N x N distance matrix for a single 'slice'
X = randn(10,10,20);
dist_matrix_tensor = @btime mapslices(dist_function, X, dims = [1,2]); # 61.172 μs (198 allocations: 42.28 KiB)
dist_matrix_tensor2 = @btime map(dist_function, Slices(X, 1, 2)); # 41.529 μs (62 allocations: 21.67 KiB)
但是请注意,JuliennedArrays returns 是 Matrix
的 Vector
而不是三维数组。
我正在尝试使用 Julia 中的 Distances
包来执行距离矩阵的广播计算。
我了解如何计算某个矩阵 X
(维度 D x N
)的单个 N x N
距离矩阵,其中每一列 X[:,i]
存储一个 D
维特征向量进行观察i
。代码将是:
using Distances
dist_matrix = pairwise(Euclidean(), X, dims = 2)
dist_matrix
包含每对 D
维列之间的欧氏距离,例如dist_matrix[m,n]
存储 X[:,m]
和 X[:,n]
之间的欧氏距离。
现在假设我的数组 X
实际上是 张量 或 'volume' 的 D
维观测值,因此 X[:,i,j]
存储我的 D x N
个观察结果中的第 j
个 'slice'。整个数组 X
因此具有维度 D x N x T
,其中 T
是切片的数量。
因此,我想计算距离矩阵的 张量 或 'volume',因此 dist_matrix
的维度为 N x N x T
。
有没有办法通过在 Julia 中广播 pairwise()
函数在一行中完成此操作?最快的方法是什么?下面显示了带有基本 for 循环的想法:
using Distances
dist_matrix_tensor = zeros(N,N,T);
for t = 1:T
dist_matrix_tensor[:,:,t] = pairwise(Euclidean(), X[:,:,t], dims = 2)
end
编辑:
我想出了如何使用 mapslices
来做到这一点,但仍然不确定这是否是最好的方法。
using Distances
dist_function(x) = pairwise(Euclidean(), x, dims = 2) # define a function that gets the N x N distance matrix for a single 'slice'
dist_matrix_tensor = mapslices(dist_function, X, dims = [1,2]) # map your matrix-operating function across the slices of the main tensor X
这当然也可以并行化,因为 X 的每个 'slice' 在此计算中都是独立的,所以我基本上只是在寻找最快的方法来执行此操作。总的来说,我也对您如何通过广播来做到这一点很感兴趣。
如果 X
的维度很大,您使用 mapslices
的解决方案的性能相当不错。下面是一个使用 JuliennedArrays 的例子,它对于小 X
稍微快一点,但是当前两个维度的大小为 100 时,它与 mapslices
具有相同的性能。
using Distances, JuliennedArrays, BenchmarkTools
dist_function(x) = pairwise(Euclidean(), x, dims = 2) # define a function that gets the N x N distance matrix for a single 'slice'
X = randn(10,10,20);
dist_matrix_tensor = @btime mapslices(dist_function, X, dims = [1,2]); # 61.172 μs (198 allocations: 42.28 KiB)
dist_matrix_tensor2 = @btime map(dist_function, Slices(X, 1, 2)); # 41.529 μs (62 allocations: 21.67 KiB)
但是请注意,JuliennedArrays returns 是 Matrix
的 Vector
而不是三维数组。