numpy 沿着轴合并Python数组

mrzz3bfm  于 2023-04-12  发布在  Python
关注(0)|答案(2)|浏览(151)

我一直在尝试填充用于Keras模型的训练数据集。使用numpy的append函数,一切都 * 工作 * 正常,但它非常慢。下面是我现在正在做的事情:

def populateData():
    images = np.zeros([1, 4, 512, 512, 6])
    for m in range(2):
        for n in range(4):
            batch_np = np.zeros([4, 512, 512, 6])

            # Doing stuff with the batch...
            # ...

            images = np.append(images, batch_np, axis=0)

随着数组的大小随着每一次遍历而增长,numpy追加新数据所需的时间几乎呈指数级增长。例如,第一次遍历大约需要1秒,第三次只需要3秒多一点。当我完成十几次或更多的时候,每个append操作都需要很多 * 分钟 *(!)。根据目前的进度,可能需要几天才能完成。

我希望能够在下一个冰河世纪之前的某个时候填充我的训练数据集。除了“获得更好的硬件”之外,如何提高np.append(...)的速度?我的理解是Numpy的append函数每次调用时都会复制整个数组。有没有等效的函数每次都不执行复制?或者使用引用值,然后修改它
我尝试使用Python的内置list append函数重写其中的一些内容,但它不像numpy的append函数那样提供axis支持。因此,虽然这看起来快得多,但它并不适用于这种多维设置。

TL;DR:Python列表追加时有没有指定轴的方法?如果没有,有没有更优化的方法,可以沿着指定轴追加到N-D数组/加速numpy.append

byqmnocz

byqmnocz1#

你可以使用np.stack和python list:

images = []
for m in range(2):
    for n in range(4):
        batch_np = np.zeros([4, 512, 512, 6])
        ...
        images.append(batch_np)
images = np.stack(images, axis=0)

输出:

>>> images.shape
(8, 4, 512, 512, 6)

或者在循环前分配整个数组:

M = 2
N = 4
images = np.zeros([M*N, N, 512, 512, 6])
for i, m in enumerate(range(M)):
    for j, n in enumerate(range(N)):
        batch_np = np.zeros([N, 512, 512, 6])
        images[i+j] = batch_np

输出:

>>> images.shape
(8, 4, 512, 512, 6)
0x6upsns

0x6upsns2#

为什么你需要指定一个轴与列表append?这两个循环产生相同的形状:

In [62]: arr = np.zeros([0,3,4])
    ...: for i in range(5):
    ...:     arr = np.append(arr, np.ones((1,3,4)), axis=0)
    ...: arr.shape
Out[62]: (5, 3, 4)

In [63]: alist = []
    ...: for i in range(5):
    ...:     alist.append(np.ones((3,4)))
    ...: arr = np.array(alist)    
In [64]: arr.shape
Out[64]: (5, 3, 4)

默认轴为0的stack执行相同的操作:

In [65]: np.stack(alist, axis=0).shape
Out[65]: (5, 3, 4)
In [66]: np.stack(alist, axis=1).shape
Out[66]: (3, 5, 4)

相关问题