把这两个向量相乘的最疯狂的方法?

2024-04-26 13:24:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个形状的数组:

A = (32,512,640)

B = (4,512)

我需要把A和B相乘,这样我就得到一个新的n数组:

C = (4,32,512,640)

另一种方法是,向量B的每一行沿着A的轴=-2相乘,结果得到一个新的1,32512640立方体。B的每一行可以循环形成123512640个立方体,然后可以使用np.concatenatenp.vstack来构建C,例如:

# Sample inputs, where the dimensions aren't necessarily known
a = np.arange(32*512*465, dtype='f4').reshape((32,512,465))
b = np.ones((4,512), dtype='f4')

# Using a loop
d = []
for row in b:
    d.append(np.expand_dims(row[None,:,None]*a, axis=0))

# Or using list comprehension
d = [np.expand_dims(row[None,:,None]*a,axis=0) for row in b]

# Stacking the final list
result = np.vstack(d)

但我想知道是否有可能使用np.einsumnp.tensordot这样的方法将这些向量化到一行中。我还在学习如何使用这两种方法,所以我不确定这是否合适。你知道吗

谢谢!你知道吗


Tags: the方法innonefornp数组list
1条回答
网友
1楼 · 发布于 2024-04-26 13:24:14

在用^{}扩展B的维数之后,我们可以利用^{}-

C = A * B[:,None,:,None]

有了^{},它将是-

C = np.einsum('ijk,lj->lijk',A,B)

这里没有求和,所以einsum不会比explicit-broadcasting好。但既然我们正在寻找Pythonic的解决方案,一旦我们超越了它的字符串表示法,就可以使用它。你知道吗

我们找点时间把事情做完-

In [15]: m,n,r,p = 32,512,640,4
    ...: A = np.random.rand(m,n,r)
    ...: B = np.random.rand(p,n)

In [16]: %timeit A * B[:,None,:,None]
10 loops, best of 3: 80.9 ms per loop

In [17]: %timeit np.einsum('ijk,lj->lijk',A,B)
10 loops, best of 3: 109 ms per loop

# Original soln
In [18]: %%timeit
    ...: d = []
    ...: for row in B:
    ...:     d.append(np.expand_dims(row[None,:,None]*A, axis=0))
    ...: 
    ...: result = np.vstack(d)
10 loops, best of 3: 130 ms per loop

杠杆multi-core

我们可以利用multi-core capability of ^{},它适合于arithmetic operationslarge data,从而在这里获得一些性能提升。让我们慢慢来-

In [42]: import numexpr as ne

In [43]: B4D = B[:,None,:,None] # this is virtually free

In [44]: %timeit ne.evaluate('A*B4D')
10 loops, best of 3: 64.6 ms per loop

在一行中为:ne.evaluate('A*B4D',{'A':A,'B4D' :B[:,None,:,None]})。你知道吗

^{}关于如何控制多核功能。你知道吗

相关问题 更多 >