对向量数组的矩阵运算

numpy.dot 可用于通过矩阵乘以向量列表,但向量的方向必须是垂直的,以便八个两个分量向量的列表看起来像两个八个分量向量:

>>> a
array([[ 1.,  2.],
       [ 3.,  1.]])
>>> b
array([[  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.],
       [  9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.]])
>>> np.dot(a, b)
array([[ 19.,  22.,  25.,  28.,  31.,  34.,  37.,  40.],
       [ 12.,  16.,  20.,  24.,  28.,  32.,  36.,  40.]])

如果向量列表的布局与其轴相反(通常是这种情况)那么数组需要在点操作之前和之后进行转置,如下所示:

>>> b
array([[  1.,   9.],
       [  2.,  10.],
       [  3.,  11.],
       [  4.,  12.],
       [  5.,  13.],
       [  6.,  14.],
       [  7.,  15.],
       [  8.,  16.]])
>>> np.dot(a, b.T).T
array([[ 19.,  12.],
       [ 22.,  16.],
       [ 25.,  20.],
       [ 28.,  24.],
       [ 31.,  28.],
       [ 34.,  32.],
       [ 37.,  36.],
       [ 40.,  40.]])

尽管点功能非常快,但有时最好使用 einsum。相当于上述内容将是:

>>> np.einsum('...ij,...j', a, b)

这有点慢,但允许顶点列表乘以相应的矩阵列表。这将是一个非常复杂的使用点的过程:

>>> a
array([[[ 0,  1],
        [ 2,  3]],
       [[ 4,  5],
        [ 6,  7]],
       [[ 8,  9],
        [10, 11]],
       [[12, 13],
        [14, 15]],
       [[16, 17],
        [18, 19]],
       [[20, 21],
        [22, 23]],
       [[24, 25],
        [26, 27]],
       [[28, 29],
        [30, 31]]])
>>> np.einsum('...ij,...j', a, b)
array([[   9.,   29.],
       [  58.,   82.],
       [ 123.,  151.],
       [ 204.,  236.],
       [ 301.,  337.],
       [ 414.,  454.],
       [ 543.,  587.],
       [ 688.,  736.]])

numpy.dot 可用于在列表中找到每个向量的点积,在另一个列表中具有相应的向量,与沿着最后一个轴的逐元素乘法和求和相比,这是非常混乱和缓慢的。像这样的东西(需要一个更大的数组来计算,但大多数被忽略)

>>> np.diag(np.dot(b,b.T))
array([  82.,  104.,  130.,  160.,  194.,  232.,  274.,  320.])

使用逐元素乘法和求和的点积

>>> (b * b).sum(axis=-1)
array([  82.,  104.,  130.,  160.,  194.,  232.,  274.,  320.])

使用 einsum 可以实现

>>> np.einsum('...j,...j', b, b)
array([  82.,  104.,  130.,  160.,  194.,  232.,  274.,  320.])