可以通过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阵列)。
答案 0 :(得分:4)
使用np.einsum
和ellipsis(...)
来计算维度数量可变的数组,如下所示 -
np.einsum('...i,...i ->...', a, a)
说明文档 -
要启用和控制广播,请使用省略号。默认 通过在左侧添加省略号来完成NumPy风格的广播 每个术语,如np.einsum('... ii-> ... i',a)。采取跟踪 第一个和最后一个轴,你可以做np.einsum('我...我',a),或做一个 具有最左侧索引而不是最右侧的矩阵矩阵乘积, 你可以做np.einsum('ij ...,jk ...-> ik ...',a,b)。
示例在2D
和1D
数组上运行 -
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.einsum
或np.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