python - Numpy einsum 二维数组的外和

标签 python numpy numpy-einsum

我尝试寻找答案,但找不到我需要的东西。如果这是一个重复的问题,我们深表歉意。

假设我有一个形状为 (n, n*m) 的二维数组。我想要做的是这个数组与其转置的外部总和,从而产生形状为 (n*m, n*m) 的数组。例如,假设我有

A = array([[1., 1., 2., 2.],
           [1., 1., 2., 2.]])

我想做 A 的外部总和和A.T这样输出是:

>>> array([[2., 2., 3., 3.],
           [2., 2., 3., 3.],
           [3., 3., 4., 4.],
           [3., 3., 4., 4.]])

请注意np.add.outer不起作用,因为它会破坏向量的输入。我可以通过这样做来实现类似的目标

np.tile(A, (2, 1)) + np.tile(A.T, (1, 2))

但这在 n 时似乎不合理和m相当大( n > 100m > 1000 )。是否可以使用 einsum 写出这个总和?我似乎无法弄清楚einsum .

最佳答案

要利用广播,我们需要将其分解为3D,然后排列轴并添加 -

n = A.shape[0]
m = A.shape[1]//n
a = A.reshape(n,m,n) # reshape to 3D
out = (a[None,:,:,:] + a.transpose(1,2,0)[:,:,None,:]).reshape(n*m,-1)

运行示例进行验证 -

In [359]: # Setup input array
     ...: np.random.seed(0)
     ...: n,m = 3,4
     ...: A = np.random.randint(1,10,(n,n*m))

In [360]: # Original soln
     ...: out0 = np.tile(A, (m, 1)) + np.tile(A.T, (1, m))

In [361]: # Posted soln
     ...: n = A.shape[0]
     ...: m = A.shape[1]//n
     ...: a = A.reshape(n,m,n)
     ...: out = (a[None,:,:,:] + a.transpose(1,2,0)[:,:,None,:]).reshape(n*m,-1)

In [362]: np.allclose(out0, out)
Out[362]: True

nm的时序 -

In [363]: # Setup input array
     ...: np.random.seed(0)
     ...: n,m = 100,100
     ...: A = np.random.randint(1,10,(n,n*m))

In [364]: %timeit np.tile(A, (m, 1)) + np.tile(A.T, (1, m))
1 loop, best of 3: 407 ms per loop

In [365]: %%timeit
     ...: # Posted soln
     ...: n = A.shape[0]
     ...: m = A.shape[1]//n
     ...: a = A.reshape(n,m,n)
     ...: out = (a[None,:,:,:] + a.transpose(1,2,0)[:,:,None,:]).reshape(n*m,-1)
1 loop, best of 3: 219 ms per loop

使用 numexpr 进一步提升性能

我们可以利用multi-core with numexpr module对于大数据并获得内存效率和性能 -

import numexpr as ne

n = A.shape[0]
m = A.shape[1]//n
a = A.reshape(n,m,n)
p1 = a[None,:,:,:]
p2 = a.transpose(1,2,0)[:,:,None,:]
out = ne.evaluate('p1+p2').reshape(n*m,-1)

具有相同大 nm 设置的时序 -

In [367]: %%timeit
     ...: # Posted soln
     ...: n = A.shape[0]
     ...: m = A.shape[1]//n
     ...: a = A.reshape(n,m,n)
     ...: p1 = a[None,:,:,:]
     ...: p2 = a.transpose(1,2,0)[:,:,None,:]
     ...: out = ne.evaluate('p1+p2').reshape(n*m,-1)
10 loops, best of 3: 152 ms per loop

关于python - Numpy einsum 二维数组的外和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52320991/

相关文章:

python - 索引在python中是什么意思?

python - docker build 期间没有名为 'numpy' 的模块

python - Numpy:为列表中的每个数组的 np.array 的每一行乘以 (1/2)^k

python - numpy数组的计算/操作

python - ipython 内核在 16gb 的 linux 盒子中最大容量为 3gb?

python - 我可以在 Google 的 ortools 包中提供一个带有 BFS 的求解器来启动吗?

numpy - 已排序的 numpy 数组的交集

python - 是否有 Numpy 或 Pandas 设置在创建 NaN 值时发出警告

python - 将这两个向量相乘的大多数 Pythonic 方法?

python - 使用 pytest 读写文件的模式