两个向量的点积的可扩展解决方案

时间:2017-02-18 12:29:46

标签: python python-2.7 numpy

可以通过numpy.dot计算两个向量的点积。现在我想计算一组向量的点积:

>>> numpy.arange(15).reshape((5, 3))
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14]])

向量是行向量,输出应该是包含点积结果的1d数组:

array([  5,  50, 149, 302, 509])

对于交叉产品(numpy.cross),可以轻松指定axis关键字。但是numpy.dot没有这样的选项,并且传递两个2d阵列将导致普通的矩阵产品。我也看了一下numpy.tensordot,但这似乎也没有(作为扩展矩阵产品)。

我知道我可以通过

计算2d阵列的每个元素的点积
>>> numpy.einsum('ij, ji -> i', array2d, array2d.T)

然而,这个解决方案对1d阵列(即只是单个元素)不起作用。我想获得一个适用于1d阵列(返回标量)和1d阵列阵列(也称为2d阵列)的解决方案(返回1d阵列)。

1 个答案:

答案 0 :(得分:4)

使用np.einsumellipsis(...)来计算维度数量可变的数组,如下所示 -

np.einsum('...i,...i ->...', a, a)

说明文档 -

  

要启用和控制广播,请使用省略号。默认   通过在左侧添加省略号来完成NumPy风格的广播   每个术语,如np.einsum('... ii-> ... i',a)。采取跟踪   第一个和最后一个轴,你可以做np.einsum('我...我',a),或做一个   具有最左侧索引而不是最右侧的矩阵矩阵乘积,   你可以做np.einsum('ij ...,jk ...-> ik ...',a,b)。

示例在2D1D数组上运行 -

In [88]: a
Out[88]: 
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14]])

In [89]: np.einsum('...i,...i ->...', a, a) # On 2D array
Out[89]: array([  5,  50, 149, 302, 509])

In [90]: b = a[:,0]

In [91]: b
Out[91]: array([ 0,  3,  6,  9, 12])

In [92]: np.einsum('...i,...i ->...', b,b) # On 1D array
Out[92]: 270

运行时测试 -

因为,我们需要保持一个轴对齐,至少与2D数组对齐,np.einsumnp.matmul中的一个或最新的@ operator会有效。

In [95]: a = np.random.rand(1000,1000)

# @unutbu's soln
In [96]: %timeit (a*a).sum(axis=-1)
100 loops, best of 3: 3.63 ms per loop

In [97]: %timeit np.einsum('...i,...i ->...', a, a)
1000 loops, best of 3: 944 µs per loop

In [98]: a = np.random.rand(1000)

# @unutbu's soln
In [99]: %timeit (a*a).sum(axis=-1)
100000 loops, best of 3: 9.11 µs per loop

In [100]: %timeit np.einsum('...i,...i ->...', a, a)
100000 loops, best of 3: 5.59 µs per loop