Python 不同尺寸的Numpy阵列广播

Python 不同尺寸的Numpy阵列广播,python,numpy,Python,Numpy,我对numpy的广播规则有点困惑。假设您希望执行高维数组的轴方向标量积,以将数组维数减少1(基本上是沿一个轴执行加权求和): 为什么V03不工作 干杯您可以用它: In [35]: np.apply_along_axis(v.dot, 2, A) Out[35]: array([[ 3., 3., 3.], [ 3., 3., 3.], [ 3., 3., 3.]]) 我认为V03不起作用的原因是,它与: B[:,:] = v.dot(A) i、

我对numpy的广播规则有点困惑。假设您希望执行高维数组的轴方向标量积,以将数组维数减少1(基本上是沿一个轴执行加权求和):

为什么V03不工作

干杯

您可以用它:

In [35]: np.apply_along_axis(v.dot, 2, A)
Out[35]: 
array([[ 3.,  3.,  3.],
       [ 3.,  3.,  3.],
       [ 3.,  3.,  3.]])
我认为
V03
不起作用的原因是,它与:

B[:,:] = v.dot(A) 
i、 e.它尝试沿着
A

的最外轴计算点积,在这种特殊情况下,您也可以使用

import numpy as np

A = np.ones((3,3,2))
v = np.array([1,2])

print np.tensordot(v, A, axes=(0, 2))
这将产生:

array([[ 3.,  3.,  3.],
       [ 3.,  3.,  3.],
       [ 3.,  3.,  3.]])
轴=(0,2)
表示
tensordot
应与
v
中的第一个轴和
A
中的第三个轴相加。(还可以看一看,它更灵活,但如果不习惯这种符号,就更难理解。)

如果考虑到速度,
tensordot
比使用
apply\u沿_轴
用于小型阵列要快得多

In [14]: A = np.ones((3,3,2))

In [15]: v = np.array([1,2])

In [16]: %timeit np.tensordot(v, A, axes=(0, 2))
10000 loops, best of 3: 21.6 us per loop

In [17]: %timeit np.apply_along_axis(v.dot, 2, A)
1000 loops, best of 3: 258 us per loop
(由于开销恒定,大型阵列的差异不太明显,尽管
tensordot
始终更快。)

np.dot(a,b)
运行。因此,对于您的问题中的特定情况,您可以始终选择:

>>> a.dot(v)
array([[ 3.,  3.,  3.],
       [ 3.,  3.,  3.],
       [ 3.,  3.,  3.]])
如果要保持v.dot(a)顺序,需要将轴定位到位,这可以通过以下方法轻松实现:

我不太喜欢
np.dot
,除非是明显的矩阵或向量乘法,因为在使用可选的
out
参数时,输出数据类型非常严格。Joe Kington已经提到了这一点,但是如果你要做这类事情,要习惯于
np.einsum
:一旦你掌握了语法的窍门,就可以将你花在重塑事物上的时间减少到最低限度:

>>> a = np.ones((3, 3, 2))
>>> np.einsum('i, jki', v, a)
array([[ 3.,  3.,  3.],
       [ 3.,  3.,  3.],
       [ 3.,  3.,  3.]])
这并不是说它在这种情况下太相关,而是它的速度也快得可笑:

In [4]: %timeit a.dot(v)
100000 loops, best of 3: 2.43 us per loop

In [5]: %timeit v.dot(np.rollaxis(a, 2, 1))
100000 loops, best of 3: 4.49 us per loop

In [7]: %timeit np.tensordot(v, a, axes=(0, 2))
100000 loops, best of 3: 14.9 us per loop

In [8]: %timeit np.einsum('i, jki', v, a)
100000 loops, best of 3: 2.91 us per loop

我发现numpy-tensordot轴完全令人困惑。你能详细说明一下吗?我想把一个(10,3,2)张量乘以一个(3,5)张量得到一个(2)张量。
>>> a = np.ones((3, 3, 2))
>>> np.einsum('i, jki', v, a)
array([[ 3.,  3.,  3.],
       [ 3.,  3.,  3.],
       [ 3.,  3.,  3.]])
In [4]: %timeit a.dot(v)
100000 loops, best of 3: 2.43 us per loop

In [5]: %timeit v.dot(np.rollaxis(a, 2, 1))
100000 loops, best of 3: 4.49 us per loop

In [7]: %timeit np.tensordot(v, a, axes=(0, 2))
100000 loops, best of 3: 14.9 us per loop

In [8]: %timeit np.einsum('i, jki', v, a)
100000 loops, best of 3: 2.91 us per loop