簡體   English   中英

我可以使用 np.vectorize() 向量化列表理解嗎?

[英]Can I vectorise a list comprehension using np.vectorize()?

我對 Python 相當NumPy ,從NumPy開始。
我嘗試執行以下操作:

a = np.arange(1, 20)  
f = np.vectorize([x/(x+1) for x in a])  
f(a)  
TypeError: 'list' object is not callable <-- got this error

所以我想知道是否可以對列表理解進行矢量化還有“對象不可調用”是什么意思? 供將來參考 提前致謝

不要浪費時間嘗試使用np.vectorize ,尤其是當您可以進行真正的numpy 矢量化時。 不要被名字所迷惑。 這不是快速數字計算的捷徑。

In [442]: a = np.arange(1,5)

你的列表理解:

In [443]: [x/(x+1) for x in a]
Out[443]: [0.5, 0.6666666666666666, 0.75, 0.8]

可以通過一個簡單的 numpy 數組操作來完成:

In [444]: a/(a+1)
Out[444]: array([0.5, 0.66666667, 0.75, 0.8])

但是讓我們假設我們有 s 函數只適用於標量輸入:

In [445]: f = np.vectorize(lambda x: x/(x+1), otypes=[float])
In [446]: f(a)
Out[446]: array([0.5, 0.66666667, 0.75 , 0.8])

它可以工作,但比 [444] 慢得多,也不比 [443] 快。

所以我想知道是否有可能對列表理解進行矢量化。

np.vectorize將一個函數轉換為一個接受數組作為輸入的函數。 然后,您可以使用它來代替列表理解。

但它不會從性能角度“矢量化”操作。 事實上,它通常較慢,用於測試或語法調整。

“對象不可調用”是什么意思?

在 Python 中,“可調用”是可以“作為函數”使用的對象。 當然,函數是可調用的。 您可以向其他對象添加__call__方法。

下面是具有__call__方法的類的示例。

In [33]: class myclass():
    ...:     def __init__(self):
    ...:         pass
    ...:     def __call__(self, x):
    ...:         return x**2
    ...: 
    ...: 

In [34]: A = myclass()

In [35]: A(10)
Out[35]: 100

[x/(x+1) for x in a]是一個表達式,它返回一個值,不能被調用。 np.vectorize的參數必須是可調用的。

這里的其他人建議使用np.vectorize(lambda x: x/(1+x))

def f(x):
    return x/(1+x)

f_vec = np.vectorize(f)

第一個是“lambda 函數”,第二個是常規函數。 兩者都是可調用的。

對於你展示的情況,你確實可以做到

y = x/(1+x)

這將使用 NumPy 操作。 由於 x 是一個數組,這被認為是一種向量化形式(計算將在優化和向量化的 C++ 代碼中進行)。

對於更復雜的計算,請查找 Cython、numexpr 或 Numba。

我認為您可能對列表理解和 np.vectorize 的作用有點困惑。 np.vectorize 以某種方式更改函數,使其可以應用於整個列表。 你應該使用的是 -

def foo(x):
    return(x/(x+1))

f = np.vectorize(foo)
a = np.arange(1, 20) 

f(a)

使用[x/(x+1) for x in a]將得到與 f(a) 相同的結果,只是執行時間不同。

您收到“列表不可調用”錯誤的原因是因為 f 是一個列表而不是一個函數,並且您正試圖將一個參數 (a) 傳遞給一個列表。

暫無
暫無

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

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