[英]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.