Python Numpy 矩阵乘法/形状不兼容/违抗数学?
Python Numpy Matrix Multiplication / Shape Not Compatible / Defying Math?
考虑以下代码:
X = np.array([[1,1,1],
[2,2,2],
[3,3,3],
[4,4,4]]) # shape of (4,3)
print("Matrix X is:\n", X)
print("\n --------- TEST 1 ---------\n")
W = np.array([1,2,3]) # 1D array (row)
print("W is:", W)
print("X * W is:\n", X*W)
print("\n --------- TEST 2 ---------\n")
W = np.array([[1,2,3]]) # 2D array (shape 1,3)
print("W is:", W)
print("X * W is:\n", X*W)
print("\n --------- TEST 3 ---------\n")
W = np.array([[1,2,3]]).T # 2D array (shape 3,1)
print("W is:\n", W)
print("X * W is:\n", X*W)
print("\n --------- TEST 4 ---------\n")
W = np.array([1,2,3]) # 1D array (row)
print("W is:\n", W)
print("X @ W is:\n", X@W.T) # dot product
print("\n --------- TEST 5 ---------\n")
W = np.array([[1,2,3]]) # 2D array (shape 1,3)
print("W is:\n", W)
print("X @ W is:\n", X@W.T) # dot product
print("\n --------- TEST 6 ---------\n")
W = np.array([[1,2,3]]).T # 2D array (shape 3,1)
print("W is:\n", W)
print("X @ W is:\n", X@W) # dot product
输出(省略测试 3)为:
Matrix X is:
[[1 1 1]
[2 2 2]
[3 3 3]
[4 4 4]]
--------- TEST 1 ---------
W is: [1 2 3]
X * W is:
[[ 1 2 3]
[ 2 4 6]
[ 3 6 9]
[ 4 8 12]]
--------- TEST 2 ---------
W is: [[1 2 3]]
X * W is:
[[ 1 2 3]
[ 2 4 6]
[ 3 6 9]
[ 4 8 12]]
--------- TEST 4 ---------
W is:
[1 2 3]
X @ W is:
[ 6 12 18 24]
--------- TEST 5 ---------
W is:
[[1 2 3]]
X @ W is:
[[ 6]
[12]
[18]
[24]]
--------- TEST 6 ---------
W is:
[[1]
[2]
[3]]
X @ W is:
[[ 6]
[12]
[18]
[24]]
问题:
测试 3 将失败并显示以下错误消息:
ValueError: operands could not be broadcast together with shapes (4,3) (3,1)
但是从数学上讲这是不正确的,应该可以正常工作。 N 列矩阵乘以 N 行矩阵或向量是有效的数学运算。在这种情况下,X 中有 3 列,W 中有 3 行。那么这是怎么回事?
我预计测试 1 和测试 2 会出现这种错误,但也许可以理解 numpy 如何 "reshape" W 以便它们匹配。但是 Test3 出错了?真的吗?
我认为这与 Numpy 中的广播有关?在数学上似乎有点违反直觉。 Numpy 是否需要让乘数的列(第二个因子/从现在开始 "F2")的形状始终与被乘数的列(第一个因子/从现在开始 "F1")相匹配?所以基本上它遍历 F1 中的每一行并将该行的每一列与 F2 的列相乘?
重新审视这个数学上正确的是:
列 F1 = 行 F2。
这似乎是:
F1 列 = F2 列。
还有更多:
在测试 3 之后将其扩展到点积,从技术上讲,测试 6 应该不起作用,但突然它起作用了(而且在数学上是正确的!)。
除此之外,测试 6 对我来说在数学上很扎实,所以这里没有问题。
我的以下假设是否正确:
测试 4:
如果 F2 是一维行向量,点积仍将完全相同(就像它是列向量一样),但它会输出一维行向量。这基本上是像这样的乘法的唯一真正区别?在引擎盖下,完全相同的工作本质上就像二维矢量一样发生?
测试 5:
所以在数学上我假设 Numpy 是 "auto-transforming" F2 (Row) 内部进入一个列,所以测试 6 和测试 5 真的是一样的。
PS:写这个问题我想我已经意识到 Numpy 再次匹配位置。几乎就像某种地图网格系统。但是,老实说,不允许进行 Test 3 仍然让我感到困惑。如果您正在寻找 "grids" 不相互对齐,这是有道理的,但肯定可以实现吗?如果测试 6 有效,我不明白为什么测试 3 不应该。
谢谢!
我认为您将 *
运算符与 @
运算符混淆了。
- 前者是逐元素乘法,两个操作数的形状必须匹配或可以是"broadcasted"。
- 后者是矩阵乘法,所以只有
X.shape[1]
和W.shape[0]
重合才能使用。
您在测试 3 中遇到的错误是因为 numpy brodcasting 遵循特定规则,这些规则可以在 here 中找到,并且不适用于测试 3,另一方面,在测试 6 中,您完全能够按预期进行矩阵乘法。
除非X
和W
是numpy.matrix
,否则*
不是用于矩阵乘法而是用于广播。
您可以在 broadcasting documentation 中查看此操作仅在
时有效
both dimensions are equal, or one of them is 1
这就是为什么它适用于测试 1 和 2 的原因。
一旦 W 具有形状 (1,3),它将在操作期间被拉伸成具有 (4,3) 形状的数组
您可以了解有关阵列广播和拉伸的更多信息here。
在测试 3 中,W 具有形状 (3,1),这会导致第一维发生冲突 (4 来自 X,3 来自 W) 因为它不遵守 2 规则上面提到。
另一方面,第二个维度会很好 (3,1)
考虑以下代码:
X = np.array([[1,1,1],
[2,2,2],
[3,3,3],
[4,4,4]]) # shape of (4,3)
print("Matrix X is:\n", X)
print("\n --------- TEST 1 ---------\n")
W = np.array([1,2,3]) # 1D array (row)
print("W is:", W)
print("X * W is:\n", X*W)
print("\n --------- TEST 2 ---------\n")
W = np.array([[1,2,3]]) # 2D array (shape 1,3)
print("W is:", W)
print("X * W is:\n", X*W)
print("\n --------- TEST 3 ---------\n")
W = np.array([[1,2,3]]).T # 2D array (shape 3,1)
print("W is:\n", W)
print("X * W is:\n", X*W)
print("\n --------- TEST 4 ---------\n")
W = np.array([1,2,3]) # 1D array (row)
print("W is:\n", W)
print("X @ W is:\n", X@W.T) # dot product
print("\n --------- TEST 5 ---------\n")
W = np.array([[1,2,3]]) # 2D array (shape 1,3)
print("W is:\n", W)
print("X @ W is:\n", X@W.T) # dot product
print("\n --------- TEST 6 ---------\n")
W = np.array([[1,2,3]]).T # 2D array (shape 3,1)
print("W is:\n", W)
print("X @ W is:\n", X@W) # dot product
输出(省略测试 3)为:
Matrix X is:
[[1 1 1]
[2 2 2]
[3 3 3]
[4 4 4]]
--------- TEST 1 ---------
W is: [1 2 3]
X * W is:
[[ 1 2 3]
[ 2 4 6]
[ 3 6 9]
[ 4 8 12]]
--------- TEST 2 ---------
W is: [[1 2 3]]
X * W is:
[[ 1 2 3]
[ 2 4 6]
[ 3 6 9]
[ 4 8 12]]
--------- TEST 4 ---------
W is:
[1 2 3]
X @ W is:
[ 6 12 18 24]
--------- TEST 5 ---------
W is:
[[1 2 3]]
X @ W is:
[[ 6]
[12]
[18]
[24]]
--------- TEST 6 ---------
W is:
[[1]
[2]
[3]]
X @ W is:
[[ 6]
[12]
[18]
[24]]
问题:
测试 3 将失败并显示以下错误消息:
ValueError: operands could not be broadcast together with shapes (4,3) (3,1)
但是从数学上讲这是不正确的,应该可以正常工作。 N 列矩阵乘以 N 行矩阵或向量是有效的数学运算。在这种情况下,X 中有 3 列,W 中有 3 行。那么这是怎么回事?
我预计测试 1 和测试 2 会出现这种错误,但也许可以理解 numpy 如何 "reshape" W 以便它们匹配。但是 Test3 出错了?真的吗?
我认为这与 Numpy 中的广播有关?在数学上似乎有点违反直觉。 Numpy 是否需要让乘数的列(第二个因子/从现在开始 "F2")的形状始终与被乘数的列(第一个因子/从现在开始 "F1")相匹配?所以基本上它遍历 F1 中的每一行并将该行的每一列与 F2 的列相乘?
重新审视这个数学上正确的是: 列 F1 = 行 F2。 这似乎是: F1 列 = F2 列。
还有更多:
在测试 3 之后将其扩展到点积,从技术上讲,测试 6 应该不起作用,但突然它起作用了(而且在数学上是正确的!)。
除此之外,测试 6 对我来说在数学上很扎实,所以这里没有问题。
我的以下假设是否正确:
测试 4:
如果 F2 是一维行向量,点积仍将完全相同(就像它是列向量一样),但它会输出一维行向量。这基本上是像这样的乘法的唯一真正区别?在引擎盖下,完全相同的工作本质上就像二维矢量一样发生?
测试 5:
所以在数学上我假设 Numpy 是 "auto-transforming" F2 (Row) 内部进入一个列,所以测试 6 和测试 5 真的是一样的。
PS:写这个问题我想我已经意识到 Numpy 再次匹配位置。几乎就像某种地图网格系统。但是,老实说,不允许进行 Test 3 仍然让我感到困惑。如果您正在寻找 "grids" 不相互对齐,这是有道理的,但肯定可以实现吗?如果测试 6 有效,我不明白为什么测试 3 不应该。
谢谢!
我认为您将 *
运算符与 @
运算符混淆了。
- 前者是逐元素乘法,两个操作数的形状必须匹配或可以是"broadcasted"。
- 后者是矩阵乘法,所以只有
X.shape[1]
和W.shape[0]
重合才能使用。
您在测试 3 中遇到的错误是因为 numpy brodcasting 遵循特定规则,这些规则可以在 here 中找到,并且不适用于测试 3,另一方面,在测试 6 中,您完全能够按预期进行矩阵乘法。
除非X
和W
是numpy.matrix
,否则*
不是用于矩阵乘法而是用于广播。
您可以在 broadcasting documentation 中查看此操作仅在
时有效both dimensions are equal, or one of them is 1
这就是为什么它适用于测试 1 和 2 的原因。 一旦 W 具有形状 (1,3),它将在操作期间被拉伸成具有 (4,3) 形状的数组
您可以了解有关阵列广播和拉伸的更多信息here。
在测试 3 中,W 具有形状 (3,1),这会导致第一维发生冲突 (4 来自 X,3 来自 W) 因为它不遵守 2 规则上面提到。 另一方面,第二个维度会很好 (3,1)