Python 二维数组的Numpy-einsum外和
我试着寻找答案,但找不到我需要的。如果这是一个重复的问题,请道歉 假设我有一个二维数组,其形状Python 二维数组的Numpy-einsum外和,python,numpy,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.],
(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>100
和m>1000
)时,这似乎不合理。是否可以使用einsum
写入此总和?我就是搞不懂einsum
一种方法是
(A.reshape(-1,*A.shape).T+A)[:,0,:]
我认为n>100
和m>1000
会占用大量内存
但这不就是
np.add.outer(A,A)[:,0,:].reshape(4,-1)
要利用
广播
,我们需要将其分解为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
大n
,m
-
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进一步提升性能
我们可以利用大量数据,提高内存效率,从而提高性能-
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)
使用相同的大型n
,m
设置进行计时-
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
einsum
实现产品的总和;它可以用于外积,但不能用于外和。使用磁贴
可以创建两个与目标大小相同的临时数组,对吗?问题是否如此之大,以至于您只能拥有一个这样大小的数组?您是否可以通过更改A
的第二行来进行诊断?从示例中退一步,重点关注维度<代码>A可以被重塑为(n,n,m),目标可以被重塑为(n,m,n,m)。如果我们可以创建一个和,即(n,n,m,m),我们可以转置得到正确的形状。这些价值观正确吗?