在大型 Numpy 数组中利用对称性
Exploiting Symmetry in Large Numpy Array
想要制作大数组 B,它由较小的 numpy 数组 A 组成,以不同的方式翻转:
B[0,:,:,:,:] = A
B[1,:,:,:,:] = B[0,:,::-1,:,:]
B[2:4,:,:,:,:] = B[0:2,:,:,::-1,:]
B[4:8,:,:,:,:] = B[0:4,:,:,:,::-1]
有没有办法只在内存中存储A,而为B保留一些numpy数组的功能?我主要对两件事感兴趣:
- 能够缩放 B[m,n,...](即 B[m,n,...] *= C 其中 B.shape[2:] == C.shape)
- 能够求和到第二个维度(即np.sum(B, axis=(2,3,4)))
我最后做的是创建一个 class 到 return 的 A 的任意反射部分的视图。我在 [=14 之后按 C 进行缩放以及求和=]ing 这个视图,目前看来已经够快了。这是没有错误检查的:
class SymmetricArray:
'''
Attributes:
A (np.ndarray): an [m, (a,b,c...)] array.
idx (np.ndarray): an [n,] array where idx[n] points to A[idx[n], ...]
to be used.
reflect (np.ndarray): an [n, d] array where every entry is 1 or -1 and
reflect[n, i] indicates whether or not the ith dimension of
A[idx[n], ...] should be reflected, and d = len(A.shape - 1).
'''
def __init__(self, A, idx, reflect):
self.A = np.asarray(A)
self.idx = np.asarray(idx, dtype=int)
self.reflect = np.asarray(reflect, dtype=int)
def __getitem__(self, ii):
'''
Returns:
np.ndarray: appropriately reflected A[idx[ii], ...]
'''
a_mask = [slice(None, None, a) for a in self.reflect[ii, :]]
return self.A[self.idx[ii], ...][a_mask]
想要制作大数组 B,它由较小的 numpy 数组 A 组成,以不同的方式翻转:
B[0,:,:,:,:] = A
B[1,:,:,:,:] = B[0,:,::-1,:,:]
B[2:4,:,:,:,:] = B[0:2,:,:,::-1,:]
B[4:8,:,:,:,:] = B[0:4,:,:,:,::-1]
有没有办法只在内存中存储A,而为B保留一些numpy数组的功能?我主要对两件事感兴趣:
- 能够缩放 B[m,n,...](即 B[m,n,...] *= C 其中 B.shape[2:] == C.shape)
- 能够求和到第二个维度(即np.sum(B, axis=(2,3,4)))
我最后做的是创建一个 class 到 return 的 A 的任意反射部分的视图。我在 [=14 之后按 C 进行缩放以及求和=]ing 这个视图,目前看来已经够快了。这是没有错误检查的:
class SymmetricArray:
'''
Attributes:
A (np.ndarray): an [m, (a,b,c...)] array.
idx (np.ndarray): an [n,] array where idx[n] points to A[idx[n], ...]
to be used.
reflect (np.ndarray): an [n, d] array where every entry is 1 or -1 and
reflect[n, i] indicates whether or not the ith dimension of
A[idx[n], ...] should be reflected, and d = len(A.shape - 1).
'''
def __init__(self, A, idx, reflect):
self.A = np.asarray(A)
self.idx = np.asarray(idx, dtype=int)
self.reflect = np.asarray(reflect, dtype=int)
def __getitem__(self, ii):
'''
Returns:
np.ndarray: appropriately reflected A[idx[ii], ...]
'''
a_mask = [slice(None, None, a) for a in self.reflect[ii, :]]
return self.A[self.idx[ii], ...][a_mask]