理解numpy.dot与N维数组和一维数组

时间:2019-01-26 07:56:51

标签: python numpy

对于不清楚我要问的问题而投票决定关闭的人,以下是我帖子中的问题:

  1. 有人可以告诉我y的结果吗?
  2. 在数学中有什么叫和积?
  3. x是否需要广播?
  4. 为什么y是列/行向量?
  5. 如果x=np.array([[7],[2],[3]])怎么办?
w=np.array([[1,2,3],[4,5,6],[7,8,9]])
x=np.array([7,2,3])
y=np.dot(w,x)

谁能告诉我y的结果是什么?

enter image description here 我特意将屏幕快照拼接起来,以便您假装自己正在测试中并且无法运行python来获取结果。

https://docs.scipy.org/doc/numpy-1.15.4/reference/generated/numpy.dot.html#numpy.dot

  

如果a是一个N-D数组而b是一个一维数组,则它是   a和b的最后一个轴。

数学中有什么叫做和积的东西吗?

x是否需要广播?

为什么y是列/行向量?

如果x=np.array([[7],[2],[3]])怎么办?

2 个答案:

答案 0 :(得分:1)

如果尺寸匹配乘法,则

np.dot就是矩阵乘法(即w为3x3,x为1x3,因此无法进行WX的矩阵乘法,但XW可以)。 第一种情况:

>>> w=np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> x=np.array([7,2,3])
>>> w.shape
(3, 3)
>>> x.shape # 1d vector
(3, )

因此,在这种情况下,它返回W的每行带有内部产品

>>> [np.dot(ww,x) for ww in w]
[20, 56, 92]
>>> np.dot(w,x)
array([20, 56, 92]) # as they are both same

更改订单

>>> y = np.dot(x,w) # matrix mult as usual
>>> y
array([36, 48, 60])

第二种情况:

>>> x=np.array([[7],[2],[3]])
>>> x.shape
(3, 1)
>>> y = np.dot(w,x) # matrix mult
>>> y
array([[20],
       [56],
       [92]])

但是,这次乘积(3x1,3x3)和内积(1x1,1x3)的时间维度都不匹配,因此会产生误差。

>>> y = np.dot(x,w)
Traceback (most recent call last):

  File "<ipython-input-110-dcddcf3bedd8>", line 1, in <module>
    y = np.dot(x,w)

ValueError: shapes (3,1) and (3,3) not aligned: 1 (dim 1) != 3 (dim 0)

答案 1 :(得分:1)

我认为您的问题不是很明确,而是过于腐。

例如,当文档使用sum product用于1d by 1d情况,而inner product用于2d by 2d情况时,为什么在这种nD 1d情况下对matrix product感到困惑?案件?像内部产品一样,给自己一些自由,将其读取为sum of the products

为使示例更清晰,请将w设置为矩形,以更好地区分行操作和列操作:

In [168]: w=np.array([[1,2,3],[4,5,6]])
     ...: x=np.array([7,2,3])
     ...: 
     ...: 
In [169]: w.shape
Out[169]: (2, 3)
In [170]: x.shape
Out[170]: (3,)

dot及其等效的einstein表示法:

In [171]: np.dot(w,x)
Out[171]: array([20, 56])
In [172]: np.einsum('ij,j->i',w,x)
Out[172]: array([20, 56])

sum of the products是在重复的j维度上完成的,而没有对i进行求和。

我们可以通过广播的逐元素乘法来做同样的事情:

In [173]: (w*x[None,:]).sum(axis=1)
Out[173]: array([20, 56])

尽管此等效操作确实使用广播,但最好不要以这些术语来考虑dot

matmul给出了相同操作的另一种描述,在x中添加了一个尺寸以形成2d by 2d矩阵乘积,然后进行挤压以删除多余的尺寸。我不认为dot是在幕后这样做的,但结果是相同的。

这也可以称为矩阵向量乘法,只要您不必坚持将1d x称为行向量或列向量即可。


现在为2d x,形状为(3,1):

In [175]: x2 = x[:,None]
In [176]: x2
Out[176]: 
array([[7],
       [2],
       [3]])
In [177]: x2.shape
Out[177]: (3, 1)
In [178]: np.dot(w,x2)
Out[178]: 
array([[20],
       [56]])
In [179]: np.einsum('ij,jk->ik',w,x2)
Out[179]: 
array([[20],
       [56]])

总和超过jw的最后一个轴,以及x的第二个到最后一个。要对元素进行相同的操作,我们必须使用广播来生成3d outer乘积,然后进行求和以将维数减小到2。

In [180]: (w[:,:,None]*x2[None,:,:]).sum(axis=1)
Out[180]: 
array([[20],
       [56]])

在此示例中,(2,3) dot (3,1) => (2,1)。这是完全正常的矩阵产品行为。在第一个(2,3) dot (3,) => (2,)中。对我来说,这是逻辑上的概括。 (3,) dot (3,) => scalar(与()相反)是一种特殊情况。

我怀疑第一种情况主要是对看到(3,)形状并认为(1,3)行向量的人来说是一个问题。由于3和1之间的不匹配,(2,3) dot (1,3)不起作用。