【问题标题】:Padding an N-dimension Matrix with different paddings for each element in the matrix - Python为矩阵中的每个元素填充具有不同填充的 N 维矩阵 - Python
【发布时间】:2021-12-30 12:13:55
【问题描述】:

我正在尝试使用不同的填充来填充 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) 以便代码在计算上有效率吗?

【问题讨论】:

    标签: python matrix multidimensional-array slice pad


    【解决方案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]]]])
    

    【讨论】:

    • 目前的答案有什么问题/反例吗?
    • 如果每个轴上总是有一个移位,则此解决方案有效。有些矩阵我想根据条件以不同的方式映射填充。提供的解决方案适用于 (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:“”
    猜你喜欢
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 2021-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多