Python 高效地将2D numpy阵列复制为3D numpy阵列的通道?

Python 高效地将2D numpy阵列复制为3D numpy阵列的通道?,python,arrays,numpy,Python,Arrays,Numpy,我想制作给定2D阵列的多个副本,并将它们存储为3D numpy阵列的通道。目前,我有以下几点: finalOut=np.zeros((800,400,3)) output_frame=np.random.randn(800,400) for i in range(finalOut.shape[-1]): finalOut[:,:,i]=output_frame 这是最快的方法吗?仔细研究一下如何使用 当然,这会将通道放置在第0轴上,因此您可能希望在之后使用以下命令移动通道: >&

我想制作给定2D阵列的多个副本,并将它们存储为3D numpy阵列的通道。目前,我有以下几点:

finalOut=np.zeros((800,400,3))
output_frame=np.random.randn(800,400)
for i in range(finalOut.shape[-1]):
    finalOut[:,:,i]=output_frame
这是最快的方法吗?

仔细研究一下如何使用

当然,这会将通道放置在第0轴上,因此您可能希望在之后使用以下命令移动通道:

>>> b = np.tile(a, (3, 1, 1))
>>> np.transpose(b, (1, 2, 0))
array([[[1, 1, 1],
        [2, 2, 2],
        [3, 3, 3]],
       [[4, 4, 4],
        [5, 5, 5],
        [6, 6, 6]]])
>>> np.transpose(b, (1, 2, 0)).shape
(2, 3, 3)
试验

最快的选择通常是使用numpy,它允许您创建一个新轴,并在必要时才使用它。例如:

>>> b = a[:, :, np.newaxis]
>>> b.shape
(2, 3, 1)
>>> b = b * np.array([1, 0, 0])   # Set G and B channels to 0.
>>> b
array([[[1, 0, 0],
        [2, 0, 0],
        [3, 0, 0]],    
       [[4, 0, 0],
        [5, 0, 0],
        [6, 0, 0]]])
然后,在通道上执行操作之前,甚至不会构建新的3D阵列。但是需要一些时间来适应……

研究如何使用

def gks(frame):
    finalOut=np.zeros((800,400,3))
    for i in range(finalOut.shape[-1]):
        finalOut[:,:,i]=frame
    return finalOut
当然,这会将通道放置在第0轴上,因此您可能希望在之后使用以下命令移动通道:

>>> b = np.tile(a, (3, 1, 1))
>>> np.transpose(b, (1, 2, 0))
array([[[1, 1, 1],
        [2, 2, 2],
        [3, 3, 3]],
       [[4, 4, 4],
        [5, 5, 5],
        [6, 6, 6]]])
>>> np.transpose(b, (1, 2, 0)).shape
(2, 3, 3)
试验

最快的选择通常是使用numpy,它允许您创建一个新轴,并在必要时才使用它。例如:

>>> b = a[:, :, np.newaxis]
>>> b.shape
(2, 3, 1)
>>> b = b * np.array([1, 0, 0])   # Set G and B channels to 0.
>>> b
array([[[1, 0, 0],
        [2, 0, 0],
        [3, 0, 0]],    
       [[4, 0, 0],
        [5, 0, 0],
        [6, 0, 0]]])
然后,在通道上执行操作之前,甚至不会构建新的3D阵列。但是需要一些时间来适应

def gks(frame):
    finalOut=np.zeros((800,400,3))
    for i in range(finalOut.shape[-1]):
        finalOut[:,:,i]=frame
    return finalOut
对于这种大小,您的代码与平铺解决方案一样好:

In [52]: frame = np.random.randn(800,400)
In [61]: np.allclose(gks(frame), np.tile(frame[:,:,None],[1,1,3]))
Out[61]: True

In [62]: timeit np.tile(frame[:,:,None],[1,1,3]).shape
100 loops, best of 3: 9.36 ms per loop

In [63]: timeit gks(frame).shape
100 loops, best of 3: 9.36 ms per loop
np.tile代码使用repeat compiled进行复制,并在复制之前和之后进行重塑,以将其应用于正确的形状

使用广播的方式多种多样,但似乎没有更快

In [70]: timeit (frame[:,:,None]+np.zeros(3)).shape
100 loops, best of 3: 11.6 ms per loop
您的循环运行良好,因为与整个阵列大小相比,大小3较小

这里有更快的东西:

def spl(frame):
    finalOut=np.zeros((800,400,3))
    finalOut[...]=frame[...,None]
    return finalOut

In [105]: timeit spl(frame)
100 loops, best of 3: 5.54 ms per loop
我很犹豫是否提出这个建议,因为我认为这将创建视图,而不是副本。但初步测试表明它是在复制

对于这种大小,您的代码与平铺解决方案一样好:

In [52]: frame = np.random.randn(800,400)
In [61]: np.allclose(gks(frame), np.tile(frame[:,:,None],[1,1,3]))
Out[61]: True

In [62]: timeit np.tile(frame[:,:,None],[1,1,3]).shape
100 loops, best of 3: 9.36 ms per loop

In [63]: timeit gks(frame).shape
100 loops, best of 3: 9.36 ms per loop
np.tile代码使用repeat compiled进行复制,并在复制之前和之后进行重塑,以将其应用于正确的形状

使用广播的方式多种多样,但似乎没有更快

In [70]: timeit (frame[:,:,None]+np.zeros(3)).shape
100 loops, best of 3: 11.6 ms per loop
您的循环运行良好,因为与整个阵列大小相比,大小3较小

这里有更快的东西:

def spl(frame):
    finalOut=np.zeros((800,400,3))
    finalOut[...]=frame[...,None]
    return finalOut

In [105]: timeit spl(frame)
100 loops, best of 3: 5.54 ms per loop
我很犹豫是否提出这个建议,因为我认为这将创建视图,而不是副本。但初步测试表明它正在复制。

您也可以使用:

根据我的测试,@hpaulj和@Praveen提出的方法比你的慢,而我的方法可以让你获得微不足道的速度增益:

In [244]: frame = np.random.randn(800, 400)

In [245]: %timeit copy_dstack(frame)
100 loops, best of 3: 4.07 ms per loop

In [246]: %timeit copy_for(frame)
100 loops, best of 3: 4.1 ms per loop

In [247]: %timeit copy_tile(frame)
100 loops, best of 3: 6.8 ms per loop

In [248]: %timeit copy_broadcasting(frame)
100 loops, best of 3: 6.71 ms per loop
我还检查了所有方法是否产生相同的结果:

In [249]: np.allclose(copy_dstack(frame), copy_for(frame))
Out[249]: True

In [250]: np.allclose(copy_for(frame), copy_tile(frame))
Out[250]: True

In [251]: np.allclose(copy_tile(frame), copy_broadcasting(frame))
Out[251]: True
您还可以使用:

根据我的测试,@hpaulj和@Praveen提出的方法比你的慢,而我的方法可以让你获得微不足道的速度增益:

In [244]: frame = np.random.randn(800, 400)

In [245]: %timeit copy_dstack(frame)
100 loops, best of 3: 4.07 ms per loop

In [246]: %timeit copy_for(frame)
100 loops, best of 3: 4.1 ms per loop

In [247]: %timeit copy_tile(frame)
100 loops, best of 3: 6.8 ms per loop

In [248]: %timeit copy_broadcasting(frame)
100 loops, best of 3: 6.71 ms per loop
我还检查了所有方法是否产生相同的结果:

In [249]: np.allclose(copy_dstack(frame), copy_for(frame))
Out[249]: True

In [250]: np.allclose(copy_for(frame), copy_tile(frame))
Out[250]: True

In [251]: np.allclose(copy_tile(frame), copy_broadcasting(frame))
Out[251]: True


在rangefinalOut.shape[-1]中为i循环:-最后一个维度的大小,而不是维度的数量它们恰好都是3。谢谢hpaulj。更正!在rangefinalOut.shape[-1]中为i循环:-最后一个维度的大小,而不是维度的数量它们恰好都是3。谢谢hpaulj。更正!不确定np.rollaxisb,0,3输出是否是我想要的。虽然现在形状是正确的,但是当我从我的方法和你的方法中减去最后一个时,绝对的差别是huge@GKS我已经编辑了我的答案,改为使用转置,并且添加了一个测试来向您展示它的工作原理。这有帮助吗?它确实有帮助,但是,它仍然没有更快。不过非常感谢你的邀请teaching@GKS很可能,这不是代码中的瓶颈。如果您可以在单独的问题中共享程序的其余部分,我们可能可以帮助加快其他操作。不确定np.rollaxisb,0,3输出是否是我想要的。虽然现在形状是正确的,但是当我从我的方法和你的方法中减去最后一个时,绝对的差别是huge@GKS我已经编辑了我的答案,改为使用转置,并且添加了一个测试来向您展示它的工作原理。这有帮助吗?它确实有帮助,但是,它仍然没有更快。不过非常感谢你的邀请teaching@GKS很可能,这不是代码中的瓶颈。如果你能在一个单独的问题中分享你程序的其余部分,我们也许可以帮助加快其他操作。我同意速度范围不大。盖尼找到了一个更快的,我想感谢hpaulj,总体上看起来更快,但我获得的速度增益非常小。@praveen我已经找到了。检查此项:。我也接受了一个答案。答案中的输出是我试图复制3个通道。我同意速度范围不大。盖尼找到了一个更快的通道,我想多亏了hpaulj,它总体上看起来更快,但我获得的速度增益非常小。@praveen我已经做到了。检查此项:。我也接受了一个答案。答案中的输出是我正在尝试为3个通道进行复制