【问题标题】:How to create a multi-dimensional result by iterating over batches of arrays如何通过迭代成批的数组来创建多维结果
【发布时间】:2019-01-21 11:51:08
【问题描述】:

我正在迭代一些输入批次并生成具有形状(BatchSize、X、Y)的结果。 BatchSize 不一定与我循环批次相同。我想返回一个输出,它是沿批处理维度的结果的串联版本。在 NumPy 中最优雅的方法是什么?

我不太担心性能,而是处理累加结果数组的多维性。

【问题讨论】:

  • 天哪,别再问这个问题了。由于您无法正确预分配,因此最好的方法是将子数组累积在一个普通的 Python 列表中,然后在最后将所有子数组连接在一起。在 SO 上有一堆 QA 线程可能会进行优化,但我描述的 cat 方法往往与其中任何一个方法一样好。

标签: python numpy


【解决方案1】:

假设您有足够的内存来保存所有结果,一个好的解决方案是简单地预先分配内存:

result = np.empty(OUTPUT_SHAPE)
i=0
while i < input_tensor.shape[0]:
    batch_size = get_batch_size(i)
    result[i:i+batch_size] = deal_with_batch(input_tensor[i:i+batch_size])
    i += batch_size

【讨论】:

  • 在移动设备上创作...请原谅任何语法错误。 :)
【解决方案2】:

The answer by @Scott 是正确的。但是,我一直在寻找我认为已经找到的增量版本:

定义results = np.empty((0, output_shape)),然后使用results = np.concatenate((results, some_func(x)))在循环中更新它

我不确定我应该如何考虑 numpy 中大小为 0 的维度,但它可以工作。

【讨论】:

  • 当心这个解决方案,因为它有二次运行时间。更好的方法是将.append 每个result 连接到list,然后在最后将它们连接一次。
  • 详细来说,np.concatenate 调用必须分配一个全新的数组并对当前的results 矩阵执行 memcpy。每个批次都会发生这种情况,results 矩阵每次都会增长。因此,我们首先 memcpy 1 个批次,然后是 2 个批次,然后是 3 个等等。sum(range[n]) ~ n^2。即,随着批次数量的增加,此解决方案的扩展性会很差。
  • 收集列表中的数组,最后做一个concatenate 是通常的建议,基于性能。增量 concatenate 有两个主要问题 - 创建起始数组并不像 alist=[] 那样简单(正如您所发现的那样),以及速度(它每次都会创建一个带有完整副本的新数组)。 List append 只是添加一个指向列表的指针,而不是一个全新的数组。
猜你喜欢
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 2011-08-15
  • 2022-01-03
  • 2017-10-24
  • 2014-04-20
  • 2011-12-28
相关资源
最近更新 更多