我有一个 nd 数组,例如这个:
x = np.array([[1,2,3],[4,5,6]])
我想将最后一个维度的大小加倍,并在元素之间插入零以填充空间。结果应该如下所示:
[[1,0,2,0,3,0],[4,0,5,0,6,0]]
我尝试使用
expand_dims
和pad
来解决它。但是 pad
函数不仅在最后一个维度的每个值之后插入零。结果的形状是(3, 4, 2)
,但应该是(2,3,2)
y = np.expand_dims(x,-1)
z = np.pad(y, (0,1), 'constant', constant_values=0)
res = np.reshape(z,[-1,2*3]
我的代码的结果:
array([[1, 0, 2, 0, 3, 0],
[0, 0, 4, 0, 5, 0],
[6, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]])
如何使用
pad
在每个元素后面的最后一个维度中插入零?或者有什么更好的方法可以解决这个问题吗?
只需初始化输出数组并使用
slicing
- 进行分配
m,n = x.shape
out = np.zeros((m,2*n),dtype=x.dtype)
out[:,::2] = x
或者堆叠 -
np.dstack((x,np.zeros_like(x))).reshape(x.shape[0],-1)
您可以使用insert功能来完成:
np.insert(arr=x, obj=[1,2,3], values=0, axis=1)
array([[1, 0, 2, 0, 3, 0],
[4, 0, 5, 0, 6, 0]])
其中
obj
是插入值的索引 before。
对我发现的一些方法进行了基准测试:
(1) 分指标赋值
(2) 跨步技巧
(3) 填充
(4) 连接
def dilation1(X, d):
Xd_shape = np.multiply(X.shape, d)
Xd = np.zeros(Xd_shape, dtype=X.dtype)
Xd[0:Xd_shape[0]:d[0], 0:Xd_shape[1]:d[1]] = X
return Xd
def dilation2(X, d):
Xd_shape = np.multiply(X.shape, d)
Xd = np.zeros(Xd_shape, dtype=X.dtype)
Xdn = np.lib.stride_tricks.as_strided(Xd, X.shape, np.multiply(Xd.strides, d))
Xdn[:] = X
return Xd
def dilation3(X, d):
Xd = X.reshape((X.shape[0],1,X.shape[1],1))
Xd = np.pad(Xd, ((0,0),(0,d[0]-1),(0,0),(0,d[1]-1)))
return Xd.reshape(np.multiply(X.shape,d))
def dilation4(X, d):
Xd = X.reshape((X.shape[0],1,X.shape[1],1))
mcol = np.zeros(Xd.shape[:3]+(d[1]-1,))
Xd = np.concatenate((Xd, mcol), 3)
mrow = np.zeros((Xd.shape[0],d[0]-1)+Xd.shape[2:])
Xd = np.concatenate((Xd, mrow), 1)
return Xd.reshape(np.multiply(X.shape,d))
#Example
b = np.arange(3*3).reshape((3,3))
b
# array([[0, 1, 2],
# [3, 4, 5],
# [6, 7, 8]])
dilation1(b, (3,2))
# array([[0, 0, 1, 0, 2, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [3, 0, 4, 0, 5, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [6, 0, 7, 0, 8, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0]])
#Benchmark
a = np.random.randn(1024,1024)
%timeit -r 20 dilation1(a, (5,5))
#19.7 ms ± 890 µs per loop (mean ± std. dev. of 20 runs, 100 loops each)
%timeit -r 20 dilation2(a, (5,5))
#18.8 ms ± 526 µs per loop (mean ± std. dev. of 20 runs, 100 loops each)
%timeit -r 20 dilation3(a, (5,5))
#101 ms ± 2.32 ms per loop (mean ± std. dev. of 20 runs, 10 loops each)
%timeit -r 20 dilation4(a, (5,5))
#101 ms ± 1.59 ms per loop (mean ± std. dev. of 20 runs, 10 loops each)
所以只需使用子索引赋值即可。
沿着你的expand_dims,我们可以使用
stack
:
In [742]: x=np.arange(1,7).reshape(2,-1)
In [743]: x
Out[743]:
array([[1, 2, 3],
[4, 5, 6]])
In [744]: np.stack([x,x*0],axis=-1).reshape(2,-1)
Out[744]:
array([[1, 0, 2, 0, 3, 0],
[4, 0, 5, 0, 6, 0]])
stack
使用 expend_dims
添加维度;它就像 np.array
但可以更好地控制如何添加新轴。因此,这是一种散布数组的便捷方法。
堆栈产生一个 (2,4,2) 数组,我们将其重塑为 (2,8)。
x*0
可以替换为 np.zeros_like(x)
,或任何创建相同大小的零数组的东西。
np.stack([x,x*0],axis=1).reshape(4,-1)
添加 0 行。
您只需填充新尺寸的一侧:
x = np.array( [[1,2,3],[4,5,6]] )
y = np.expand_dims(x,-1)
z = np.pad( y, ((0, 0), (0, 0), (0, 1)) , 'constant', constant_values=0)
res = np.reshape(z, ( x.shape[0] , 2*x.shape[1] ) )
res
array([[1, 0, 2, 0, 3, 0],
[4, 0, 5, 0, 6, 0]])
>>> import numpy as np
>>> from scipy.signal import upfirdn
>>> x = np.array([[1, 2, 3], [4, 5, 6]])
>>> upfirdn([1], x, 2)
array([[1., 0., 2., 0., 3.],
[4., 0., 5., 0., 6.]])
>>> upfirdn([1], x, 3)
array([[1., 0., 0., 2., 0., 0., 3.],
[4., 0., 0., 5., 0., 0., 6.]])
第一个参数是 FIR 滤波器系数,使用 [1]
将使值保持不变。第三个参数是零的数量-1。