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
将其与单个已编译代码进行比较时,这是太多的工作了。再次声明:不是与这些相关的编译细节方面的专家。