Python 向量数学——numpy与迭代器

Python 向量数学——numpy与迭代器,python,numpy,Python,Numpy,下面的代码显示迭代器比numpy.array快得多(除非我做错了什么) 迭代器版本不仅可以使用迭代器,还可以使用np.array、list或tuple 所以,这里是提出客观问题的地方,我猜这是一个客观的原因,numpy经常被用于这类事情(根据我在互联网上看到的情况) 这是什么原因?还是我客观上做错了什么?我会说你做错了,但这是一个解释问题,取决于你正在解决的问题的细节 在本例中,您将二维numpy数组存储为numpy数组列表,然后使用“列表处理”例程。这规避了numpy中可能的一些好处/优化 下

下面的代码显示迭代器比numpy.array快得多(除非我做错了什么)

迭代器版本不仅可以使用迭代器,还可以使用np.array、list或tuple

所以,这里是提出客观问题的地方,我猜这是一个客观的原因,numpy经常被用于这类事情(根据我在互联网上看到的情况)


这是什么原因?还是我客观上做错了什么?

我会说你做错了,但这是一个解释问题,取决于你正在解决的问题的细节

在本例中,您将二维numpy数组存储为numpy数组列表,然后使用“列表处理”例程。这规避了numpy中可能的一些好处/优化

下面给出了在ipython中运行的案例的稍微修改版本(不运行%pylab)。请注意,在本例中,您使用的不是itertools,而是内置的
iter()
函数

import numpy as np

dim = 10000
arrays = [np.array((1, 2, 3)) for x in range(dim)]
iterators = [iter((1, 2, 3)) for x in range(dim)]

%timeit sum(arrays)
10 loops, best of 3: 20.8 ms per loop

%timeit list(sum(x) for x in zip(*iterators))
1000 loops, best of 3: 468 µs per loop
[根据以下评论进行编辑。]

因此迭代器看起来很棒,但它们有一个限制,即只能使用一次;在我们迭代它们之后,它们现在是“空的”。因此,使用%timeit的正确测试应该是每次重新创建迭代器

def iter_test () :
    iterators = [iter((1, 2, 3)) for x in range(dim)]
    return list(sum(x) for x in zip(*iterators))

%timeit iter_test()
100 loops, best of 3: 4.06 ms per loop
现在我们看到它(仅)比在阵列上循环快5倍左右

在纯numpy中,我会执行以下操作(二维数组可以通过多种方式创建)


因此,这个应该快得多。

我想说你做错了,但这是一个解释问题,取决于你正在解决的问题的细节

在本例中,您将二维numpy数组存储为numpy数组列表,然后使用“列表处理”例程。这规避了numpy中可能的一些好处/优化

下面给出了在ipython中运行的案例的稍微修改版本(不运行%pylab)。请注意,在本例中,您使用的不是itertools,而是内置的
iter()
函数

import numpy as np

dim = 10000
arrays = [np.array((1, 2, 3)) for x in range(dim)]
iterators = [iter((1, 2, 3)) for x in range(dim)]

%timeit sum(arrays)
10 loops, best of 3: 20.8 ms per loop

%timeit list(sum(x) for x in zip(*iterators))
1000 loops, best of 3: 468 µs per loop
[根据以下评论进行编辑。]

因此迭代器看起来很棒,但它们有一个限制,即只能使用一次;在我们迭代它们之后,它们现在是“空的”。因此,使用%timeit的正确测试应该是每次重新创建迭代器

def iter_test () :
    iterators = [iter((1, 2, 3)) for x in range(dim)]
    return list(sum(x) for x in zip(*iterators))

%timeit iter_test()
100 loops, best of 3: 4.06 ms per loop
现在我们看到它(仅)比在阵列上循环快5倍左右

在纯numpy中,我会执行以下操作(二维数组可以通过多种方式创建)


所以这个应该快得多。

问题在于:

arrays = [np.array((1, 2, 3)) for x in range(dim)]
不是数组,这是:

sum(arrays)
这不是一个裸体手术

将计时与阵列列表和内置的
总和
进行比较:

>>> timeit.timeit('sum(arrays)', 'from __main__ import arrays', number=1000)
16.348400657162813
>>> actual_array = numpy.array(arrays)
>>> timeit.timeit('numpy.sum(actual_array, axis=0)', 'from __main__ import actua
l_array; import numpy', number=1000)
0.20679712685881668
使用2D数组和
numpy.sum
获得的结果:

>>> timeit.timeit('sum(arrays)', 'from __main__ import arrays', number=1000)
16.348400657162813
>>> actual_array = numpy.array(arrays)
>>> timeit.timeit('numpy.sum(actual_array, axis=0)', 'from __main__ import actua
l_array; import numpy', number=1000)
0.20679712685881668

80倍的改进。它比迭代器版本快5倍。如果要使用NumPy,则需要在NumPy中保留尽可能多的工作。

问题在于:

arrays = [np.array((1, 2, 3)) for x in range(dim)]
不是数组,这是:

sum(arrays)
这不是一个裸体手术

将计时与阵列列表和内置的
总和
进行比较:

>>> timeit.timeit('sum(arrays)', 'from __main__ import arrays', number=1000)
16.348400657162813
>>> actual_array = numpy.array(arrays)
>>> timeit.timeit('numpy.sum(actual_array, axis=0)', 'from __main__ import actua
l_array; import numpy', number=1000)
0.20679712685881668
使用2D数组和
numpy.sum
获得的结果:

>>> timeit.timeit('sum(arrays)', 'from __main__ import arrays', number=1000)
16.348400657162813
>>> actual_array = numpy.array(arrays)
>>> timeit.timeit('numpy.sum(actual_array, axis=0)', 'from __main__ import actua
l_array; import numpy', number=1000)
0.20679712685881668

80倍的改进。它比迭代器版本快5倍。如果要使用NumPy,则需要尽可能多地使用NumPy。矢量可以存储在内存中以供进一步计算,而迭代器不能,如果不存储在高度相关的位置,则该值将消失:。这可能是重复的…
numpy
向量可以存储在内存中以供进一步计算,而迭代器不能,如果不存储在高度相关的位置,该值将消失:。这可能是重复的…我想你搞错了迭代器版本的计时。迭代器在第一次运行后被使用,因此所有后续运行都计算空和。@user2357112很好,您当然是正确的。我已经更新了答案。结果现在更有意义了。我想你把迭代器版本的时间安排搞砸了。迭代器在第一次运行后被使用,因此所有后续运行都计算空和。@user2357112很好,您当然是正确的。我已经更新了答案。现在,结果更有意义了。