我使用itertools.product生成长度为13的4个元素的所有可能变体.4和13可以是任意的,但实际上,我得到4 ^ 13个结果,这是很多。我需要将结果作为Numpy数组,目前执行以下操作:
c = it.product([1,-1,np.complex(0,1), np.complex(0,-1)], repeat=length)
sendbuf = np.array(list(c))
在两者之间插入一些简单的分析代码,看起来第一行几乎是即时的,而转换为列表然后Numpy数组需要大约3个小时。 有没有办法让这更快?我可能会忽视它,这可能是非常明显的事情。
谢谢!
答案 0 :(得分:13)
相当于itertools.product()
的NumPy是numpy.indices()
,但它只能获得0,...,k-1形式范围的乘积:
numpy.rollaxis(numpy.indices((2, 3, 3)), 0, 4)
array([[[[0, 0, 0],
[0, 0, 1],
[0, 0, 2]],
[[0, 1, 0],
[0, 1, 1],
[0, 1, 2]],
[[0, 2, 0],
[0, 2, 1],
[0, 2, 2]]],
[[[1, 0, 0],
[1, 0, 1],
[1, 0, 2]],
[[1, 1, 0],
[1, 1, 1],
[1, 1, 2]],
[[1, 2, 0],
[1, 2, 1],
[1, 2, 2]]]])
对于您的特殊情况,您可以使用
a = numpy.indices((4,)*13)
b = 1j ** numpy.rollaxis(a, 0, 14)
(这不会在32位系统上运行,因为数组很大。从我可以测试的大小推断,它应该在不到一分钟的时间内运行。)
EIDT:提一下:对numpy.rollaxis()
的调用或多或少具有考验性,以获得与itertools.product()
相同的输出。如果你不关心索引的顺序,你可以省略它(但只要你没有任何后续操作可以将你的数组转换成一个连续的数组,它就很便宜。)
EDIT2:获得
的确切类似物numpy.array(list(itertools.product(some_list, repeat=some_length)))
你可以使用
numpy.array(some_list)[numpy.rollaxis(
numpy.indices((len(some_list),) * some_length), 0, some_length + 1)
.reshape(-1, some_length)]
这完全不可读 - 只要告诉我是否应该进一步解释:)
答案 1 :(得分:5)
第一行似乎是瞬间,因为没有进行实际操作。生成器对象只是在构建时才会构建,并且只有在操作发生时才进行迭代。正如您所说,您获得了4^13 = 67108864
个号码,所有这些都是在list
来电期间计算并提供的。我看到np.array只接受列表或元组,因此您可以尝试从迭代器中创建一个元组并将其传递给np.array以查看是否存在任何性能差异并且它不会影响程序的整体性能。这可以通过尝试使用你的用例来确定,尽管some points表示元组稍快一些。
尝试使用元组而不是列表只需执行
sendbuf = np.array(tuple(c))
答案 2 :(得分:5)
您可以通过跳转到列表来加快速度:
numpy.fromiter(c, count=…) # Using count also speeds things up, but it's optional
使用此函数,首先分配NumPy数组,然后逐个元素进行初始化,而不必完成列表构造的附加步骤。
PS :fromiter()
无法处理product()
返回的元组,因此现在可能不是解决方案。如果fromiter()
确实处理了dtype=object
,那么这应该可行。
PPS :正如Joe Kington指出的那样,这可以通过putting the tuples in a structured array来实现。但是,这似乎并不总能加快速度。
答案 3 :(得分:2)
您可能想要尝试完全不同的方法:首先创建一个所需大小的空数组:
result = np.empty((4**length, length), dtype=complex)
然后使用NumPy的切片技能自己填充数组:
# Set up of the last "digit":
result[::4, length-1] = 1
result[1::4, length-1] = -1
result[2::4, length-1] = 1j
result[3::4, length-1] = -1j
你可以为其他“数字”(即结果[:,2],结果[:,1]和结果[:,0])的元素做类似的事情。整个事情当然可以放在一个遍历每个数字的循环中。
转置整个操作(np.empty((length, 4**length)…)
)值得尝试,因为它可能会带来速度增加(通过更好地使用内存缓存)。
答案 4 :(得分:1)
可能没有优化,但更不依赖于python类型的转换:
ints = [1,2,3,4]
repeat = 3
def prod(ints, repeat):
w = repeat
l = len(ints)
h = l**repeat
ints = np.array(ints)
A = np.empty((h,w), dtype=int)
rng = np.arange(h)
for i in range(w):
x = l**i
idx = np.mod(rng,l*x)/x
A[:,i] = ints[idx]
return A
答案 5 :(得分:0)
length = 13
x = [1, -1, 1j, -1j]
mesh = numpy.meshgrid(*([x] * length))
result = numpy.vstack([y.flat for y in mesh]).T
在我的笔记本上需要约2分钟