我使用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个小时。有没有办法让这个过程更快?这可能是我忽略的一些非常明显的东西。
谢谢!
发布于 2011-01-17 23:29:31
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)]这变得完全不可读--只需告诉我是否应该进一步解释它:)
发布于 2011-01-17 10:37:53
第一行看起来是瞬间的,因为没有发生任何实际的操作。生成器对象是刚刚构造的,并且仅当您在操作发生时遍历它时才会构造它。正如您所说,您将获得4^13 = 67108864编号,所有这些编号都是在您的list调用期间计算并提供的。我看到np.array只接受列表或元组,所以您可以尝试在迭代器之外创建一个元组,并将其传递给np.array,以查看是否存在任何性能差异,并且它不会影响程序的整体性能。这只能通过尝试你的用例来确定,尽管有some points说元组稍微快一些。
要尝试使用元组,而不是列表,只需这样做
sendbuf = np.array(tuple(c))发布于 2011-01-17 21:36:33
您可以通过跳过到列表的转换来加快速度:
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来实现。然而,这似乎并不总是能加快速度。
https://stackoverflow.com/questions/4709510
复制相似问题