Lumen

Lumen

Eager to know more, about the world, about the intelligence, and about myself.
github

numpy 陣列是行向量還是列向量

tldr: 它是行向量,只是在進行矩陣乘法時自動擴展 / 轉換為適當的維度。

我一直被「numpy 陣列是行向量還是列向量」這個問題困擾。我知道對於一維向量來說,它既不是行也不是列,正如其他人所指出的。但如果沒有對這個問題的正確理解,每次我試圖想像在實現自己的代數時會發生什麼,我都不夠自信,而這種不自信真的很煩人,因為我總是擔心自己可能寫錯了什麼。

我將這個問題視為,當一個 2-D numpy 陣列(即矩陣)和一個 1-D numpy 陣列相乘時,這個 2-D numpy 陣列的哪個維度進行矩陣乘法。這並不簡單,因為理論上雙方都可以運作,但它們產生的結果卻完全不同。因此,今天我使用簡單的 Python 互動式命令行一次性解決這個問題。

簡單實驗#

定義一個矩陣 m

>>> m = np.array([[1,2,3],[2,3,4],[3,4,5]])
>>> m
array([[1, 2, 3],
       [2, 3, 4],
       [3, 4, 5]])

定義一個向量 v

>>> v = np.array([1,2,3])
>>> v
array([1, 2, 3])

進行元素逐位相乘:

>>> m * v
array([[ 1,  4,  9],
       [ 2,  6, 12],
       [ 3,  8, 15]])

這很直觀:兩個組件中的所有最小元素(3 維陣列)逐位相乘。

直接進行矩陣乘法:

>>> m @ v
array([14, 20, 26])
>>> v @ m
array([14, 20, 26])

有趣的是,雙向的結果都是相同的。因為交換律不適用於矩陣乘法,不僅 m @ vv @ m 不應該有相同的輸出,而且至少一方應該不是有效操作。因此,結果表明 在 numpy 操作 @ 中發生了隱式轉換

這種隱式轉換既聰明又愚蠢 —— 聰明在於它使解釋器推斷形狀,以便 它們可以猜測你想寫什麼。但這也意味著如果你在代碼中犯了邏輯錯誤,恰好被正確推斷,解釋器將繼續執行而不會拋出錯誤,甚至不會給你適當的警告,即使你正在進行錯誤的計算。這也是阻礙我對底層實際發生的事情充滿信心的罪魁禍首。

消除隱式轉換#

因此,為了消除這種模糊的空間,我們手動將向量廣播到相同的 2-D 陣列並看看會發生什麼。正如預期的那樣,這次我們可以看到它們是如何被不同對待的:

>>> v[None,:]
array([[1, 2, 3]])

# 左乘這個向量
>>> v[None,:] @ m
array([[14, 20, 26]])

# 右乘這個向量
>>> m @ v[None,:]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 1 is different from 3)

另一邊的情況也是一樣:

>>> v[:,None]
array([[1],
       [2],
       [3]])
>>> m @ v[:,None]
array([[14],
       [20],
       [26]])
>>> v[:, None] @ m
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 3 is different from 1)

結論#

所以最終答案很明確,單個向量在其核心被視為矩陣中的行向量。無需擔心,numpy 的世界現在在我心中是完美有序的;)。我希望這種隱式轉換從一開始就沒有實現,那樣我可能會更早學到這個事實,只需幾個運行時錯誤。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。