我尝试运行如下代码:
>>> import numpy as np
>>> A = np.array([[1,2], [3,4], [5,6]])
>>> A.shape
(3, 2)
>>> B = np.array([7,8])
>>> B.shape
(2,)
>>> np.dot(A,B)
array([23, 53, 83])
我认为 np.dot(A,B) 的形状应该是 (1,3) 而不是 (3,)。
矩阵返回的结果应该是:
数组([[23],[53],[83]])
23
53
83
不是
数组([23,53,83])
23 53 83
为什么会出现这个结果?
请您参考如下方法:
顾名思义,numpy.dot() 函数的主要目的是通过对两个数组执行传统线性代数点积 来提供标量结果相同形状的 (m,)。
鉴于此主要目的,documentation numpy.dot() 的第一个也谈到了这种情况(下面的第一个要点):
numpy.dot(a, b, out=None)
1. If both a and b are 1-D arrays, it is inner product of vectors (without complex conjugation).
2. If both a and b are 2-D arrays, it is matrix multiplication, but using matmul or a @ b is preferred.
3. If either a or b is 0-D (scalar), it is equivalent to multiply and using numpy.multiply(a, b) or a * b is preferred.
4. If a is an N-D array and b is a 1-D array, it is a sum product over the last axis of a and b.
您的案例包含在他的评论中的上述第 4 个要点(正如@hpaulj 所指出的)。 但是,它仍然没有完全回答您的问题,即为什么结果的形状为 (3,),而不是您预期的 (3,1)。
只有当 B 的形状为 (2,1) 时,您才有理由期待 (3,1) 的结果形状>。在这种情况下,由于 A 的形状为 (3,2),而 B 的形状为 (2,1),您有理由期待 (3,1) 的结果形状。
但是在这里,B 的形状是(2,),而不是(2,1)。因此,我们现在处于通常矩阵乘法规则管辖范围之外的领域。因此,结果如何完全取决于 numpy.dot() 函数的设计者。他们本可以选择将此视为错误(“维度不匹配”)。相反,他们选择处理这种情况,如 this answer 中所述。 .
我引用了那个答案,并做了一些修改以关联您的代码:
According to numpy a 1D array has only 1 dimension and all checks are done against that dimension. Because of this we find that np.dot(A,B) checks second dimension of A against the one dimension of B
因此,检查会成功,numpy 不会将其视为错误。
现在,唯一剩下的问题是为什么结果形状是 (3,) 而不是 (3,1) 或 (1,3) 。
答案是:在形状为(3,2) 的A 中,我们消费 最后一部分(2,) 执行和积。 A 形状的 未使用 部分是 (3,),因此 np.dot(A,B) 结果的形状>,将是 (3,)。为了进一步理解这一点,如果我们举一个不同的例子,其中 A 的形状是 (3,4,2),而不是 (3,2) ,A 形状的未消耗部分将是 (3,4,),而 np.dot(A ,B) 将是 (3,4,) 而不是您的示例生成的 (3,)。
下面是验证码:
import numpy as np
A = np.arange(24).reshape(3,4,2)
print ("A is:\n", A, ", and its shape is:", A.shape)
B = np.array([7,8])
print ("B is:\n", B, ", and its shape is:", B.shape)
C = np.dot(A,B)
print ("C is:\n", C, ", and its shape is:", C.shape)
这个的输出是:
A is:
[[[ 0 1]
[ 2 3]
[ 4 5]
[ 6 7]]
[[ 8 9]
[10 11]
[12 13]
[14 15]]
[[16 17]
[18 19]
[20 21]
[22 23]]] , and its shape is: (3, 4, 2)
B is:
[7 8] , and its shape is: (2,)
C is:
[[ 8 38 68 98]
[128 158 188 218]
[248 278 308 338]] , and its shape is: (3, 4)
另一个有助于理解此示例中的行为的视角如下:
形状为(3,4,2)的数组A可以在概念上可视化为内部数组的外部数组,其中外部数组的形状为 (3,4),每个内部数组的形状都是(2,)。因此,在这些内部数组中的每一个上,将使用数组 B(其形状为 (2,))执行传统的点积,结果标量全部保留在各自的位置,组成一个(3,4)形状(外矩阵形状)。所以,numpy.dot(A,B)的整体结果,由所有这些就地标量结果组成,形状为 (3,4)。
