提问人:Paddy 提问时间:12/30/2021 更新时间:12/31/2021 访问量:263
为矩阵中的每个元素填充 N 维矩阵 - Python
Padding an N-dimension Matrix with different paddings for each element in the matrix - Python
问:
我正在尝试用不同的填充填充 N 维矩阵的二维并覆盖这些值。请看以下示例:
def determineShifts(layer):
u = range(0, 2*layer + 1)
b = range(0, 2*layer + 1)
shifts = []
mat = np.zeros((2 * layer + 1, 2 * layer + 1), dtype=object)
for x, i in enumerate(u):
for y, j in enumerate(b):
up = (j, 2*layer - j)
left = (i, 2*layer - i)
mat[x, y] = (left, up)
return mat
layer = 1
b = np.ones((3,3,3,3))
shifts = determineShifts(layer)
我想填充数组 b 的倒数第二个和最后一个维度,使得结果的形状为 (3,3,5,5) 并覆盖该矩阵的元素并对所有节点重复该过程,在本例中为 (3,3)。我宁愿覆盖这些值(目前我收到广播错误),而不是复制所需的形状并遍历第一和第二维度。下面包括一个示例:
c = np.ones((3,3,5,5))
for i in range(np.shape(c)[0]):
for j in range(np.shape(c)[1]):
c[i,j] = np.pad(b[i,j], shifts[i,j])
有没有办法将函数应用于矩阵,以将所有移位应用于每个元素 (3,3, 3, 3) -> (3, 3, 5, 5),以便代码在计算上是有效的?
答:
0赞
Pierre D
12/31/2021
#1
np.pad()
根据您的示例,每个轴接受不同的填充值,但不能接受每个轴内的不同填充值。
一种通用方法是对元素的重新定位进行一些算术运算,然后使用花哨的索引。在您的例子中,您似乎正在尝试错开最后两个维度的 2D 块,使它们以 1 移动:轴 0 垂直移动,轴 1 水平移动。
您可以使用以下算术执行相同的操作:
def stagger_ix(s):
r = np.arange(np.prod(s))
block = r // np.prod(s[-2:])
shift_i, shift_j = block // s[1], block % s[1]
i, j = r // s[-1] % s[-2], r % s[-1]
newshape = np.array(s)
newshape[-2:] += newshape[:2] - 1
ix = (
block * np.prod(newshape[-2:])
+ (i + shift_i) * newshape[-1]
+ (j + shift_j)
)
return newshape, ix
def stagger(b):
newshape, ix = stagger_ix(b.shape)
# now insert b in a zero(newshape), as per shift logic
c = np.zeros(np.prod(newshape), dtype=b.dtype)
c[ix] = b.ravel()
c = c.reshape(newshape)
return c
您的阵列可以通过以下方式获取:c
c = stagger(np.ones((3,3,3,3)))
其他例子 -
# for example matrices
def rp1(s):
return (np.arange(np.prod(s)) + 1).reshape(s)
>>> stagger(rp1((2,2,2,2)))
array([[[[ 1, 2, 0],
[ 3, 4, 0],
[ 0, 0, 0]],
[[ 0, 5, 6],
[ 0, 7, 8],
[ 0, 0, 0]]],
[[[ 0, 0, 0],
[ 9, 10, 0],
[11, 12, 0]],
[[ 0, 0, 0],
[ 0, 13, 14],
[ 0, 15, 16]]]])
>>> stagger(rp1((2,3,2,5)))
array([[[[ 1, 2, 3, 4, 5, 0, 0],
[ 6, 7, 8, 9, 10, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0]],
[[ 0, 11, 12, 13, 14, 15, 0],
[ 0, 16, 17, 18, 19, 20, 0],
[ 0, 0, 0, 0, 0, 0, 0]],
[[ 0, 0, 21, 22, 23, 24, 25],
[ 0, 0, 26, 27, 28, 29, 30],
[ 0, 0, 0, 0, 0, 0, 0]]],
[[[ 0, 0, 0, 0, 0, 0, 0],
[31, 32, 33, 34, 35, 0, 0],
[36, 37, 38, 39, 40, 0, 0]],
[[ 0, 0, 0, 0, 0, 0, 0],
[ 0, 41, 42, 43, 44, 45, 0],
[ 0, 46, 47, 48, 49, 50, 0]],
[[ 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 51, 52, 53, 54, 55],
[ 0, 0, 56, 57, 58, 59, 60]]]])
评论
0赞
Pierre D
1/5/2022
当前答案是否有任何问题/反例?
0赞
Paddy
1/5/2022
如果每个轴上总是有一个偏移,则此解决方案有效。在一些矩阵中,我想根据条件以不同的方式映射填充。提供的解决方案在 (3,3,3,3) -> (3,3,5,5) 中效果很好。但是,在 (x, y) 的任一轴上,映射可能是 (5,5,3,3) -> (5,5,5,5) (不是 (5,5,7,7)),具体取决于我们是在 x 还是 y 处。在这些点上,完成的矩阵应该是每个 3 x 3(L、R、T、B:左、右、顶和下各一个零的填充)顶行:(2R、2B) (2R、2B) (1L1R、2B) (2L、2B) (2L、2B) 2:“” 3:(2R、1T1B) ...(2L,1T1B)4:(2L,2T)...(2L, 2T) 5: “”
评论