给定一个数组 x ,形状(2,n,m)和一组索引 [i,j] 其中 i,j< n ,我试图获得一个形状(2,m)的数组,其中第一个数组位于索引 [0,i] 和第二个数组在索引 [1,j] 。这是用于推广到形状(b,n,m)的数组和一组长度为 b 的索引的测试用例。
此操作的明显选择是 np.choose ,但这与预期的行为不同。我们希望将第一个数组的行 i 与第二个数组的行 j 配对。但是,当使用 np.choose([i,j],x)时, np.choose 会对中的第一个列进行配对数组索引为 i ,其中第二列来自数组,索引为 j (可在下面的代码中看到)得到一个形状(n,m)的数组。显然这个任务很容易用for循环执行,但由于用例(在Keras中作为张量的自定义函数,禁止迭代)我不能这样做。是否有使用Keras后端函数或Numpy执行此操作的矢量化方法?我目前正在使用" map"要做到这一点,如果我弄明白,我会用自己的答案进行更新。
这是一段代码片段,向您展示np.choose如何处理(2,n,m)数组:
>>> import numpy as np
>>> x = np.random.rand(2,4,2)
>>> choices = [3,1]
>>> np.choose(choices,x)
ValueError: invalid entry in choice array
>>> np.choose([0,0],x)
#Returns an array with x[0,:,0] and x[0,:,1] in shape(4,2)
答案 0 :(得分:1)
我相信你可以使用advanced indexing。举个例子:
import numpy as np
x = np.random.randint(0,10,(2,4,3))
x
是:
[[[0 4 1]
[8 8 1]
[3 3 6]
[4 7 8]]
[[7 1 2]
[5 9 9]
[0 4 0]
[7 8 3]]]
现在x[[0,1],[3,1],:]
是:
[[4 7 8]
[5 9 9]]
这可以扩展到(b,m,n)
问题:
import numpy as np
x = np.random.randint(0,10,(100,200,300))
choices= np.random.randint(0,200,(100))
def loop():
res=np.empty((100,300),int)
for i in range(100):
res[i]=x[i,choices[i]]
return res
一些性能测试:
In [30]: %timeit loop()
10000 loops, best of 3: 140 µs per loop
In [31]: %timeit x[arange(100),choices,:]
10000 loops, best of 3: 23.7 µs per loop
这里的索引方法只比循环快6倍,因为任务 (提取)无法利用内存对齐。
最后,您可以通过loop2=numba.njit(loop)
及时编译来增强循环。
In [32]: %timeit loop2()
10000 loops, best of 3: 32 µs per loop
表明索引方法是最优的。