【问题标题】:Mapping functions of 2D numpy arrays2D numpy 数组的映射函数
【发布时间】:2011-02-15 21:22:59
【问题描述】:

我有一个函数foo,它将一个 NxM numpy 数组作为参数并返回一个标量值。我有一个 AxNxM numpy 数组 data,我想在其上映射 foo 给我一个长度为 A 的结果 numpy 数组。

目前,我正在这样做:

result = numpy.array([foo(x) for x in data])

它有效,但似乎我没有利用 numpy 魔法(和速度)。有没有更好的办法?

我查看过numpy.vectorizenumpy.apply_along_axis,但它们都不适用于二维数组的函数。

编辑:我正在对 24x24 图像补丁进行增强回归,所以我的 AxNxM 类似于 1000x24x24。我在上面所说的 foo 将类似 Haar 的功能应用于补丁(因此,计算量不是很大)。

【问题讨论】:

  • 可能有一种方法可以重新编码foo,以便它可以接受任意维度的 numpy 数组,并将其计算应用于最后两个轴。但我们必须看看foo 是如何编码的,才能提出具体的建议。
  • 我添加了更多关于我的具体问题的详细信息。将data 保留原样,重新编码foo 以获取索引参数,然后对其进行矢量化并将其映射到arange(len(x)) 上是否有意义?

标签: python numpy


【解决方案1】:

如果 NxM 很大(比如 100),那么迭代 A 的成本将基本上摊销到零。

假设数组是 1000 X 100 X 100。

迭代是 O(1000),但内部函数的累积成本是 O(1000 X 100 X 100) - 慢了 10,000 倍。 (注意,我的术语有点不靠谱,但我知道我在说什么)

我不确定,但你可以试试这个:

result = numpy.empty(data.shape[0])
for i in range(len(data)):
    result[i] = foo(data[i])

您会在构建列表时节省大量内存分配......但循环开销会更大。

或者您可以编写循环的并行版本,并将其拆分到多个进程中。这可能会快很多,具体取决于foo 的密集程度(因为它必须抵消数据处理)。

【讨论】:

  • 变体:result = np.fromiter(itertools.imap(f, data), dtype=data.dtype, count=data.shape[0])
【解决方案2】:

您可以通过将 3D 数组重塑为具有相同前导维度的 2D 数组来实现此目的,并通过根据foo 的要求对 1D 数组进行重塑,将您的函数 foo 包装为适用于 1D 数组的函数。一个例子(使用trace而不是foo):

from numpy import *

def apply2d_along_first(func2d, arr3d):
    a, n, m = arr3d.shape
    def func1d(arr1d):
        return func2d(arr1d.reshape((n,m)))
    arr2d = arr3d.reshape((a,n*m))
    return apply_along_axis(func1d, -1, arr2d)

A, N, M = 3, 4, 5
data = arange(A*N*M).reshape((A,N,M))

print data
print apply2d_along_first(trace, data)

输出:

[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]
  [10 11 12 13 14]
  [15 16 17 18 19]]

 [[20 21 22 23 24]
  [25 26 27 28 29]
  [30 31 32 33 34]
  [35 36 37 38 39]]

 [[40 41 42 43 44]
  [45 46 47 48 49]
  [50 51 52 53 54]
  [55 56 57 58 59]]]
[ 36 116 196]

【讨论】:

  • np.fromiter(imap( 变体比 apply2d_..() 快 3-5 倍
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-28
  • 2017-07-24
  • 2011-10-13
  • 1970-01-01
  • 2018-07-13
相关资源
最近更新 更多