简体   繁体   English

为什么二维数组与一维数组的numpy点积会产生一维数组?

[英]Why does numpy Dot product of 2d array with 1d array produce 1d array?

I try to run the code like below:我尝试运行如下代码:

>>> 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])

I thought the shape of np.dot(A,B) should be (1,3) not (3,).我认为np.dot(A,B)的形状应该是 (1,3) 而不是 (3,)。

The result of matrix return should be:矩阵返回的结果应该是:

array([[23],[53],[83]])数组([[23],[53],[83]])

23
53
83

not不是

array([23,53,83])数组([23,53,83])

23 53 83

why the result occurred?结果为什么发生?

As its name suggests, the primary purpose of the numpy.dot() function is to deliver a scalar result by performing a traditional linear algebra dot product on two arrays of identical shape (m,) .顾名思义, numpy.dot()函数的主要目的是通过在两个形状相同的数组(m,)上执行传统的线性代数点积来提供标量结果。

Given this primary purpose, the documentation of numpy.dot() also talks about this scenario as the first (the first bullet point below):鉴于这个主要目的, 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.

Your case is covered by the 4 th bullet point above (as pointed out by @hpaulj) in his comments.您的案例在他的评论中包含在上面的第 4 点(如@hpaulj 所指出的)中。 But then, it still does not fully answer your question as to why the result has shape (3,) , and not (3,1) as you expected.但是,它仍然没有完全回答您的问题,即为什么结果具有形状(3,)而不是您预期的(3,1)

You are justified in expecting a result-shape of (3,1) , only if shape of B is (2,1) .你期待的结果,形状是有道理的(3,1)仅当形状B(2,1) In such a case, since A has shape (3,2) , and B has shape (2,1) , you'd be justified in expecting a result-shape of (3,1) .在这种情况下,由于A形状为(3,2) ,而B形状为(2,1) ,因此您有理由期待(3,1)的结果形状。

But here, B has a shape of (2,) , and not (2,1) .但在这里, B的形状为(2,) ,而不是(2,1) So, we are now in a territory that's outside the jurisdiction of the usual rules of matrix multiplication .因此,我们现在处于矩阵乘法通常规则管辖范围之外的领域 So, it's really up to the designers of the numpy.dot() function as to how the result turns out to be.因此,结果如何真正取决于numpy.dot()函数的设计者。 They could've chosen to treat this as an error ("dimension mis-match").他们本可以选择将此视为错误(“尺寸不匹配”)。 Instead, they've chosen to deal with this scenario, as described in this answer .相反,他们选择处理这种情况,如本回答中所述

I'm quoting that answer, with some modifications to relate your code:我引用了那个答案,并进行了一些修改以关联您的代码:

According to numpy a 1D array has only 1 dimension and all checks are done against that dimension.根据 numpy,一维数组只有一维,所有检查都是针对该维进行的。 Because of this we find that np.dot(A,B) checks second dimension of A against the one dimension of B因此,我们发现 np.dot(A,B) 根据 B 的一维检查 A 的第二维

So, the check would succeed, and numpy wouldn't treat this as an error.因此,检查会成功,并且 numpy 不会将此视为错误。

Now, the only remaining question is why is the result-shape (3,) and not (3,1) or (1,3) .现在,唯一剩下的问题是为什么结果形状是(3,)而不是(3,1)(1,3)

The answer to this is: in A , which has shape (3,2) , we have consumed the last part (2,) to perform sum-product.这个问题的答案是:在A ,它具有形状(3,2)我们consumed的最后部分(2,)执行和积。 The un-consumed part of A's shape is (3,) , and hence the shape of the result of np.dot(A,B) , would be (3,) . A 形状的un-consumed部分是(3,) ,因此np.dot(A,B)的结果形状将是(3,) To understand this further, if we take a different example in which A has a shape of (3,4,2) , instead of (3,2) , the un-consumed part of A 's shape would be (3,4,) , and the result of np.dot(A,B) would be (3,4,) instead of (3,) which your example produced.为了进一步理解这一点,如果我们举一个不同的例子,其中A的形状为(3,4,2)而不是(3,2)A形状的未消耗部分将是(3,4,) ,并且np.dot(A,B)将是(3,4,)而不是您的示例生成的(3,)

Here's the code for you to verify:这是供您验证的代码:

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)

The output of this is:这个的输出是:

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)

Another helpful perspective to understand the behavior in this example is below:另一个有助于理解此示例中行为的观点如下:

The array A of shape (3,4,2) can be conceptually visualized as an outer array of inner arrays, where the outer array has shape (3,4) , and each inner array has shape (2,) .形状为(3,4,2)的数组A可以在概念上可视化为内部数组的外部数组,其中外部数组的形状为(3,4) ,每个内部数组的形状为(2,) On each of these inner arrays, the traditional dot product will therefore be performed using the array B (which has shape (2,) , and the resulting scalars are all left in their own respective places, to form a (3,4) shape (the outer matrix shape). So, the overall result of numpy.dot(A,B) , consisting of all these in-place scalar results, would have the shape (3,4) .因此,在这些内部数组中的每一个上,传统的点积将使用数组B (形状为(2,) ,结果标量都留在各自的位置,以形成(3,4)形状) (外部矩阵形状)因此,由所有这些就地标量结果组成的numpy.dot(A,B)的整体结果将具有形状(3,4)

In wiki在维基

在此处输入图片说明

So (3, 2) dot with (2,1) will be (3,1)所以 (3, 2) 点与 (2,1) 将是 (3,1)


How to fix怎么修

np.dot(A,B[:,None])
Out[49]: 
array([[23],
       [53],
       [83]])

I just learned this dot product from Neural Network... Anyway, it is the dot product between " 1d " array and " nd " array.我刚刚从神经网络中学到了这个点积......无论如何,它是“ 1d ”数组和“ nd ”数组之间的点积。 enter image description here在此处输入图片说明

As we can see, it calculates the sum of the multiplication for elements separately in the red box as "1 7 + 2 8" Then enter image description here如我们所见,它分别计算了红色框中元素的乘法和为“1 7 + 2 8” 然后在此处输入图像描述

Then enter image description here然后在这里输入图片描述

A.shape is (3, 2), B.shape is (2,) this situation could directly use the rule #4 for the dot operation np.dot(A,B): A.shape is (3, 2), B.shape is (2,) 这种情况可以直接使用规则#4进行点操作np.dot(A,B):

If a is an ND array and b is a 1-D array, it is a sum product over the last axis of a and b .如果 a 是 ND 数组而 b 是一维数组,则它是 a 和 b 的最后一个轴上的和积

Because the alignment will happen between B's 2 (only axis of B) and A's 2 (last axis of A) and 2 indeed equals 2, numpy will judge that this is absolutely legitimate for dot operation.因为对齐会发生在 B 的 2(只有 B 的轴)和 A 的 2(A 的最后一个轴)和 2 确实等于 2 之间,所以 numpy 会判断这对于点操作是绝对合法的。 Therefore these two "2" are "consumed", leaving A's (3,) "in the wild".因此,这两个“2”被“消耗”,而 A 的 (3,) 则“在野外”。 This (3,) will therefore be the shape of the result.因此,这 (3,) 将是结果的形状。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM