2D numpy数组的映射函数

6
我有一个名为foo的函数,它接受一个NxM的numpy数组作为参数并返回一个标量值。 我有一个AxNxM的numpy数组data,我想对其进行映射foo,以便给我一个长度为A的numpy数组作为结果。
目前,我的做法是:
result = numpy.array([foo(x) for x in data])

它能工作,但似乎我没有利用numpy的魔力(和速度)。有更好的方法吗?我看过numpy.vectorize和numpy.apply_along_axis,但对于一个2D数组的函数都不起作用。编辑:我正在对24x24图像块进行增强回归,所以我的AxNxM大约是1000x24x24。我上面称之为foo的东西将一个特征应用于一个块(因此,计算上并不是非常复杂)。

1
可能有一种方法可以重新编码 foo,使其能够接受任意维度的numpy数组,并将其计算应用于最后两个轴。但我们必须查看 foo 的编码以提出具体建议。 - unutbu
我已经添加了更多关于我的具体问题的细节。将data保持不变,重新编写foo以接受索引参数,然后对其进行向量化并映射到arange(len(x))上,这样做是否有意义? - perimosocordiae
2个回答

2
如果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的强度(因为它必须抵消数据处理)。

5
变量:result = np.fromiter(itertools.imap(f, data), dtype=data.dtype, count=data.shape[0])翻译:将函数f应用于数据data中的每个元素并生成一个迭代器,使用np.fromiter方法将迭代器转换为NumPy数组,并将数据类型设置为与data相同,数组的长度为data的长度。将转换后的数组赋值给变量result。 - jfs

1
你可以通过将你的3D数组重塑为具有相同前导维度的2D数组,并使用一个函数将你的foo函数包装起来,使其能够处理1D数组并按照foo所需的方式进行重塑来实现这一点。以下是一个示例(使用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]

1
np.fromiter(imap() 变体比 apply2d_..() 快3-5倍。 - jfs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接