Python 两个向量点积的可伸缩解

Python 两个向量点积的可伸缩解,python,python-2.7,numpy,Python,Python 2.7,Numpy,两个向量的点积可通过以下公式计算:。现在我想计算向量数组的点积: >>> 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.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.dot
没有这样的选项,将两个2d数组传递给它将得到普通的矩阵积。我也看了一下,但这似乎也不起作用(作为扩展矩阵积)

我知道我可以通过

>>> numpy.einsum('ij, ji -> i', array2d, array2d.T)
但是,此解决方案不适用于一维阵列(即,仅一个元素)。我想获得一个既适用于一维数组(返回标量)又适用于一维数组数组(也称为二维数组)(返回一维数组)的解决方案。

使用
省略号(…)
来解释维数可变的数组,如下所示-

np.einsum('...i,...i ->...', a, a)
说明上面的文件-

要启用和控制广播,请使用省略号。违约 NumPy风格的广播是通过在屏幕左侧添加省略号来完成的 每个术语,如np.einsum(“…ii->…i',a)。追踪 对于第一个轴和最后一个轴,可以使用np.einsum('i…i',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
或最新的一个将是有效的

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

很好的解决方案,谢谢!我还发现可以使用
numpy.linalg.norm(array,axis=-1)**2
,但是性能与
(a*a.sum)(axis=-1)
(即与
einsum
相比较差),这让我感到非常惊讶,因为我看不到对
einsum
的调用与
linalg.norm
函数有什么不同(除了平方外,但我验证了这一贡献可以忽略不计)。你知道为什么这两个函数有如此不同的性能吗?(除非
linalg.norm
的计算结果为
sqrt((a*a).sum(axis=-1))
,但是
einsum
有什么不同之处?)@我没有深入研究einsum的实现,但基于它的性能,我认为它是一个C编译代码。现在,使用
numpy.linalg.norm
再次基于它的性能,我认为元素乘法和求和是这类编译代码的两个阶段,最重要的是
numpy.linalg.norm
,我们需要sqrt,然后您需要进行平方运算以获得所需的输出,当您使用
einsum
将其与单个已编译代码进行比较时,这是太多的工作了。再次声明:不是与这些相关的编译细节方面的专家。