【发布时间】:2020-02-29 01:27:26
【问题描述】:
我有两个尺寸为 S x F 的 numpy 数组 R 和尺寸为 N x M x F 的 W >。具体让我们分配以下值N = 5、M = 7、F = 3、S = 4
数组 R 包含一组样本 S = 4 和 F = 3 特征。每行代表一个样本,每一行代表一个特征。因此R[0] 是第一个样本,R[1] 是第二个样本,然后继续。每个R[i-th] 条目,都包含F 元素,例如R[0] = np.array([1, 4, -2])。
这是一个小 sn-p 来初始化所有这些值,并考虑到 MWE
import numpy as np
# Size of Map (rows, columns)
N, M = 5, 7
# Number of features
F = 3
# Sample size
S = 4
np.random.seed(13)
R = np.random.randint(0, 10, size=(S, F))
W = np.random.randint(-4, 5, size=(N, M, F))
我们还可以看到 numpy 数组 W的给定“深度线”,作为一个向量,也与数组的每一行具有相同的维度 R(查看两个数组的最后一个维度的大小很容易注意到这一点)。这样我就可以访问W[2, 3] 并获得np.array([ 2, 2, -1 ])(这里的值只是示例)。
我创建了一个简单的函数来计算给定向量 r 到矩阵 W 的每个 “深度线” 的距离以及返回W深度线距离r
最近的元素的位置def nearest_vector_matrix_naive(r, W):
delta = np.zeros((N,M), dtype=int)
for i in range(N):
for j in range(M):
norm = 0
for k in range(F):
norm += (r[k] - W[i,j,k])**2
delta[i,j] = norm
norm = 0
win_idx = np.unravel_index(np.argmin(delta, axis=None), delta.shape)
return win_idx
当然这是一种非常幼稚的方法,我可以进一步优化下面的代码,获得巨大的性能提升。
def nearest_vector_matrix(r, W):
delta = np.sum((W[:,:] - r)**2, axis=2)
return np.unravel_index(np.argmin(delta, axis=None), delta.shape)
我可以像使用这个函数一样简单
nearest_idx = nearest_vector_matrix(R[0], W)
# Returns the nearest vector in W to R[0]
W[nearest_idx]
由于我的数组 R 包含一堆样本,因此我使用以下 sn-p 来计算最接近样本数组的向量:
def nearest_samples_matrix(R, W):
DELTA = np.zeros((R.shape[0],2))
for idx, r in enumerate(R):
delta = np.sum((W[:,:] - r)**2, axis=2)
DELTA[idx] = np.unravel_index(np.argmin(delta, axis=None), delta.shape)
return DELTA
此函数返回一个数组,其中包含 S 行(S 是样本数)的二维索引。那就是 DELTA 具有 (S, 2) 形状(始终)。
我想知道如何替换nearest_samples_matrix 中的for 循环(例如用于广播)以进一步提高代码执行性能?
我不知道该怎么做。 (除了我在第一种情况下能够做到)
【问题讨论】:
-
数组的实际大小是多少?例如。你的参数F?如果 F 非常小,Kdtree 方法将比所有这些蛮力算法快得多。docs.scipy.org/doc/scipy/reference/generated/…
-
是的。 F远小于S、N或M。实际上讲量级:S >> N = M >> F,
-
但是 F 可以大到 100。阅读文档 F 大于 20 并不比蛮力好。
-
如果 K-Dtree 至少和蛮力方法一样快,我可以在全局范围内使用它,并在 F 维度较小时获得一些好处。