簡體   English   中英

從列表理解和一般情況下有效地創建 numpy 數組

[英]Efficient creation of numpy arrays from list comprehension and in general

在我目前的工作中,我經常使用 Numpy 和列表​​推導式,為了獲得最佳性能,我有以下問題:

如果我按如下方式創建一個 Numpy 數組,幕后實際會發生什么?

a = numpy.array( [1,2,3,4] )

我的猜測是 python 首先創建一個包含值的普通列表,然后使用列表大小分配一個 numpy 數組,然后將值復制到這個新數組中。 這是正確的,還是解釋器足夠聰明以意識到列表只是中間的,而是直接復制值?

同樣,如果我想使用numpy.fromiter()從列表numpy.fromiter()創建一個 numpy 數組:

a = numpy.fromiter( [ x for x in xrange(0,4) ], int )

這會導致在被送入fromiter()之前創建一個中間值列表嗎?

我相信您正在尋找的答案是使用帶有numpy.fromiter 的generator expressions

numpy.fromiter((<some_func>(x) for x in <something>),<dtype>,<size of something>)

生成器表達式是惰性的——當你遍歷它們時,它們會評估表達式。

使用列表推導式生成列表,然后將其輸入 numpy,而生成器表達式將一次生成一個。

Python 會從內到外評估事物,就像大多數語言(如果不是全部)一樣,因此[<something> for <something_else> in <something_different>]使用[<something> for <something_else> in <something_different>]將生成列表,然后對其進行迭代。

您可以創建自己的列表並對其進行試驗以了解情況...

>>> class my_list(list):
...     def __init__(self, arg):
...         print 'spam'
...         super(my_list, self).__init__(arg)
...   def __len__(self):
...       print 'eggs'
...       return super(my_list, self).__len__()
... 
>>> x = my_list([0,1,2,3])
spam
>>> len(x)
eggs
4
>>> import numpy as np
>>> np.array(x)
eggs
eggs
eggs
eggs
array([0, 1, 2, 3])
>>> np.fromiter(x, int)
array([0, 1, 2, 3])
>>> np.array(my_list([0,1,2,3]))
spam
eggs
eggs
eggs
eggs
array([0, 1, 2, 3])

針對標題中的問題,現在有一個叫numba的包,支持numpy array comprehension ,直接構造numpy數組,不需要中間python列表。 numpy.fromiter不同,它還支持嵌套理解。 但是,請記住,如果您不熟悉 numba,它有一些限制和性能怪癖。

也就是說,它可以非常快速和高效,但是如果您可以使用 numpy 的向量運算來編寫它,最好讓它更簡單。

>>> from timeit import timeit
>>> # using list comprehension
>>> timeit("np.array([i*i for i in range(1000)])", "import numpy as np", number=1000)
2.544344299999999
>>> # using numpy operations
>>> timeit("np.arange(1000) ** 2", "import numpy as np", number=1000)
0.05207519999999022
>>> # using numpy.fromiter
>>> timeit("np.fromiter((i*i for i in range(1000)), dtype=int, count=1000)",
...        "import numpy as np",
...        number=1000)
1.087984500000175
>>> # using numba array comprehension
>>> timeit("squares(1000)",
... """
... import numpy as np
... import numba as nb
... 
... @nb.njit
... def squares(n):
...     return np.array([i*i for i in range(n)])
... 
... 'compile the function'
... squares(10)
... """,
... number=1000)
0.03716940000003888

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM