3

在python 3.5中,引入了@運算符進行矩陣乘法運算,跟在PEP465後面。這是通過例如在numpy作爲matmul operator使矩陣乘法運算符@爲numpy中的標量運算

然而,由於提出的PEP,當一個標量操作數稱爲numpy的運營商拋出異常:

>>> import numpy as np 
>>> np.array([[1,2],[3,4]]) @ np.array([[1,2],[3,4]]) # works 
array([[ 7, 10], 
     [15, 22]]) 
>>> 1 @ 2            # doesn't work 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
TypeError: unsupported operand type(s) for @: 'int' and 'int' 

這對我來說是一個真正的關斷,因爲我實現數字信號處理算法應該適用於標量和矩陣。這兩種情況下的方程式在數學上完全等價,這並不奇怪,因爲「1-D x 1-D矩陣乘法」等價於標量乘法。然而,目前的狀態迫使我編寫重複的代碼,以便正確處理這兩種情況。

因此,鑑於目前的狀態並不令人滿意,是否有任何合理的方法可以使@運營商適用於標量?我想過爲標量數據類型添加一個自定義的__matmul__(self, other)方法,但考慮到涉及的內部數據類型的數量,這似乎很麻煩。我是否可以將numpy數組數據類型的__matmul__方法的實現更改爲不引發1x1數組操作數的異常?

而且,在這個設計決策背後的理由是什麼?從我的頭頂來看,我想不出有什麼令人信服的理由不要爲標量實現這個操作符。

+0

'[1] @ [2]'怎麼樣?標量已經有'*'爲什麼要複製它。 – furas

+4

聽起來像真正的問題是你的代碼有時會返回標量,有時會返回矩陣。爲什麼不重構,以便您的代碼返回1 x 1矩陣而不是標量?或者編寫一個快速函數,該函數採用矩陣或標量並返回該矩陣或帶有標量的1x1矩陣 –

+0

爲什麼不能使用try - except例程? – Jalo

回答

1

由於ajcr建議,您可以通過強制對象上的一些最小維數相乘來解決此問題。有兩個合理的選項:atleast_1datleast_2d,它們在@返回的類型方面有不同的結果:標量與1乘1的二維數組。

x = 3 
y = 5 
z = np.atleast_1d(x) @ np.atleast_1d(y) # returns 15 
z = np.atleast_2d(x) @ np.atleast_2d(y) # returns array([[15]]) 

然而:

  • 使用atleast_2d將導致一個錯誤,如果x和y是一維陣列,否則將被正常地乘以
  • 使用atleast_1d將導致要麼是該產品標量或矩陣,你不知道哪個。
  • 這兩個都比np.dot(x, y)更詳細,它可以處理所有這些情況。

此外,atleast_1d版本還存在相同的缺陷,也可以通過標量@ scalar =標量共享:您不知道可以對輸出做什麼。將z.Tz.shape拋出一個錯誤?這些適用於1乘1的矩陣,但不適用於標量。在Python的設置中,我們不能忽視標量和1乘1陣列之間的區別,同時也不會放棄後者所具有的所有方法和屬性。