问题描述
我想将任意函数应用于3d-ndarray作为元素,它使用3维数组作为参数并返回标量.因此,我们应该获得2d-Matrix.
I want to apply arbitrary function to 3d-ndarray as element, which use (3rd-dimensional) array for its arguments and return scalar.As a result, we should get 2d-Matrix.
例如,伪代码
A = [[[1,2,3],[4,5,6]],
[[7,8,9],[10,11,12]]]
A.apply_3d_array(sum) ## or apply_3d_array(A,sum) is Okey.
>> [[6,15],[24,33]]
我知道使用ndarray.shape函数进行循环是可能的,但是直接索引访问效率很低,如官方文档所述.有没有比使用循环更有效的方法?
I understand it's possible with loop using ndarray.shape function,but direct index access is inefficient as official document says.Is there more effective way than using loop?
def chromaticity(pixel):
geo_mean = math.pow(sum(pixel),1/3)
return map(lambda x: math.log(x/geo_mean),pixel )
推荐答案
鉴于函数实现,我们可以使用 NumPy ufuncs
可以一次性对整个输入数组A
进行操作,从而避免了不支持数组矢量化的math
库函数.在此过程中,我们还将引入非常有效的矢量化工具: .因此,我们将有一个像这样的实现-
Given the function implementation, we could vectorize it using NumPy ufuncs
that would operate on the entire input array A
in one go and thus avoid the math
library functions that doesn't support vectorization on arrays. In this process, we would also bring in the very efficient vectorizing tool : NumPy broadcasting
. So, we would have an implementation like so -
np.log(A/np.power(np.sum(A,2,keepdims=True),1/3))
示例运行和验证
不具有lamdba
构造并引入NumPy函数而不是math
库函数的函数实现,看起来像这样-
The function implementation without the lamdba
construct and introducing NumPy functions instead of math
library functions, would look something like this -
def chromaticity(pixel):
geo_mean = np.power(np.sum(pixel),1/3)
return np.log(pixel/geo_mean)
通过迭代实现运行示例-
Sample run with the iterative implementation -
In [67]: chromaticity(A[0,0,:])
Out[67]: array([-0.59725316, 0.09589402, 0.50135913])
In [68]: chromaticity(A[0,1,:])
Out[68]: array([ 0.48361096, 0.70675451, 0.88907607])
In [69]: chromaticity(A[1,0,:])
Out[69]: array([ 0.88655887, 1.02009026, 1.1378733 ])
In [70]: chromaticity(A[1,1,:])
Out[70]: array([ 1.13708257, 1.23239275, 1.31940413])
使用建议的矢量化实现运行示例-
Sample run with the proposed vectorized implementation -
In [72]: np.log(A/np.power(np.sum(A,2,keepdims=True),1/3))
Out[72]:
array([[[-0.59725316, 0.09589402, 0.50135913],
[ 0.48361096, 0.70675451, 0.88907607]],
[[ 0.88655887, 1.02009026, 1.1378733 ],
[ 1.13708257, 1.23239275, 1.31940413]]])
运行时测试
In [131]: A = np.random.randint(0,255,(512,512,3)) # 512x512 colored image
In [132]: def org_app(A):
...: out = np.zeros(A.shape)
...: for i in range(A.shape[0]):
...: for j in range(A.shape[1]):
...: out[i,j] = chromaticity(A[i,j])
...: return out
...:
In [133]: %timeit org_app(A)
1 loop, best of 3: 5.99 s per loop
In [134]: %timeit np.apply_along_axis(chromaticity, 2, A) #@hpaulj's soln
1 loop, best of 3: 9.68 s per loop
In [135]: %timeit np.log(A/np.power(np.sum(A,2,keepdims=True),1/3))
10 loops, best of 3: 90.8 ms per loop
这就是为什么在对数组进行向量化并始终尽可能多地处理多个元素时总是尝试按NumPy funcs
的原因!
That's why always try to push in NumPy funcs
when vectorizing things with arrays and work on as many elements in one-go as possible!
这篇关于如何使用numpy将函数有效地应用于三维数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!