如果你不关心输出的形状,你可以通过改变元数据来做这个操作
x = np.array([[1, 2], [3, 4]])
np.lib.stride_tricks.as_strided(x, (4,2,2), (8,0,0))
输出:
array([[[1, 1],
[1, 1]],
[[2, 2],
[2, 2]],
[[3, 3],
[3, 3]],
[[4, 4],
[4, 4]]])
此外,np.block 将提供所需的输出形状(通过复制)
x = np.lib.stride_tricks.as_strided(x, (4,2,2), (8,0,0))
np.block([[x[0], x[1]],
[x[2], x[3]]])
输出:
array([[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]])
np.block也可以使用transpose和reshape模拟:
x = np.lib.stride_tricks.as_strided(x, (1,2,2,2,2), (32,16,0,8,0))
x.reshape(4,4) # copy!
输出:
array([[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]])
不过,这会像np.block 一样复制内存。您可以尝试通过x.shape = (4,4) 直接设置形状来验证这一点:
AttributeError: Incompatible shape for in-place modification. Use `.reshape()` to make a copy with the desired shape.
以同样的方式,只需更改形状和步幅即可对输出进行下采样:
np.lib.stride_tricks.as_strided(x, (2,2), (8*8,8*2))
输出:
array([[1, 2],
[3, 4]])
请注意,这是在没有任何复制的情况下完成的。我与8 相乘的原因是它是 64 位整数的字节大小。
通用解决方案
def upsample(x, k):
return np.lib.stride_tricks.as_strided(x, (np.prod(x.shape), k, k), (x.dtype.itemsize, 0, 0))