首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >itertools产品加速

itertools产品加速
EN

Stack Overflow用户
提问于 2011-01-17 10:20:49
回答 6查看 8.9K关注 0票数 15

我使用itertools.product生成长度为13的4个元素的所有可能的变体。4和13可以是任意的,但实际上,我得到了4^13的结果,这是很多的。我需要一个Numpy数组形式的结果,当前执行以下操作:

代码语言:javascript
复制
  c = it.product([1,-1,np.complex(0,1), np.complex(0,-1)], repeat=length)
  sendbuf = np.array(list(c))

通过在中间插入一些简单的分析代码,第一行看起来几乎是瞬间的,而转换为列表和Numpy数组需要大约3个小时。有没有办法让这个过程更快?这可能是我忽略的一些非常明显的东西。

谢谢!

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2011-01-17 23:29:31

itertools.product()的NumPy等效项是numpy.indices(),但它只能得到形式为0,...,k-1的范围的乘积:

代码语言:javascript
复制
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]]]])

对于您的特殊情况,您可以使用

代码语言:javascript
复制
a = numpy.indices((4,)*13)
b = 1j ** numpy.rollaxis(a, 0, 14)

(这不能在32位系统上运行,因为数组太大了。从我可以测试的大小推断,它应该在不到一分钟内运行。)

EIDT:只想提一下:对numpy.rollaxis()的调用或多或少是为了获得与itertools.product()相同的输出。如果您不关心索引的顺序,您可以直接省略它(但是,只要您没有任何后续操作将您的数组转换为连续的数组,那么这样做的代价是很低的)。

EDIT2:要获得与

代码语言:javascript
复制
numpy.array(list(itertools.product(some_list, repeat=some_length)))

您可以使用

代码语言:javascript
复制
numpy.array(some_list)[numpy.rollaxis(
    numpy.indices((len(some_list),) * some_length), 0, some_length + 1)
    .reshape(-1, some_length)]

这变得完全不可读--只需告诉我是否应该进一步解释它:)

票数 17
EN

Stack Overflow用户

发布于 2011-01-17 10:37:53

第一行看起来是瞬间的,因为没有发生任何实际的操作。生成器对象是刚刚构造的,并且仅当您在操作发生时遍历它时才会构造它。正如您所说,您将获得4^13 = 67108864编号,所有这些编号都是在您的list调用期间计算并提供的。我看到np.array只接受列表或元组,所以您可以尝试在迭代器之外创建一个元组,并将其传递给np.array,以查看是否存在任何性能差异,并且它不会影响程序的整体性能。这只能通过尝试你的用例来确定,尽管有some points说元组稍微快一些。

要尝试使用元组,而不是列表,只需这样做

代码语言:javascript
复制
sendbuf = np.array(tuple(c))
票数 5
EN

Stack Overflow用户

发布于 2011-01-17 21:36:33

您可以通过跳过到列表的转换来加快速度:

代码语言:javascript
复制
numpy.fromiter(c, count=…)  # Using count also speeds things up, but it's optional

使用此函数,首先分配NumPy数组,然后逐个元素对其进行初始化,而不必执行额外的列表构造步骤。

PSfromiter()不处理product()返回的元组,因此目前这可能不是一个解决方案。但是,如果fromiter()确实处理了dtype=object,那么这应该是可行的。

PPS:正如Joe Kington所指出的,这可以通过putting the tuples in a structured array来实现。然而,这似乎并不总是能加快速度。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4709510

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档