简体   繁体   English

使用numpy.nditer()

[英]Use of numpy.nditer()

I have a numpy.ndarray x of shape (...,3) ie with an arbitrary number of axes, the last axis having a known size of 3. I also have a function f that takes as argument an array of shape (3) (in fact a point in a 3D space) and returns another array of shape (3) (in fact a vector in a 3D space). 我有一个形状(...,3)的numpy.ndarray x ,即具有任意数量的轴,最后一个轴的已知大小为3。我也有一个函数f ,它将形状数组(3) (实际上是3D空间中的一个点),然后返回形状(3)另一个数组(实际上是3D空间中的向量)。 Unfortunately, this function cannot (at least easily) be vectorized. 不幸的是,该功能不能(至少很容易)被矢量化。

Using numpy.nditer , how can I efficiently parse the array x along all its axes except the last one in order to fill an array y (whose shape is equal to the one of x ) with the result of f ? 使用numpy.nditer ,我如何才能有效地解析除最后一个数组之外的所有其他方向的数组x ,以便用f的结果填充数组y (其形状等于x的形状)?

The following piece of code will do it without use of nditer : 以下代码无需使用nditer即可完成此操作:

import numpy as np

def f(x):
   '''Simple function for this exemple.
   Can only deal with array of shape (3,)
   '''
   assert x.ndim == 1 and x.shape[0] == 3
   y = np.zeros_like(x)
   y[0] = x[0]
   y[1] = x[1]**2
   y[2] = x[2]**3
   return y

x = np.arange(15).reshape(5,3)

_x = x.reshape(-1,3)
_y = np.zeros_like(_x)
for i in xrange(_x.shape[0]):
    _y[i,:] = f(_x[i,:])
y = _y.reshape(x.shape)

but does not look 'pythonic' to me. 但对我来说看起来并不“ pythonic”。

As a bonus question, will there be an advantage in terms of speed in using nditer rather than the classical python loop above ? 作为一个额外的问题,使用nditer而不是上面的经典python循环在速度方面是否会有优势?

The core of what you are doing is reshaping the array to 2d, iterating on one axis, and reshaping back 您要做的核心是将数组重塑为2d,在一个轴上迭代,然后重塑

_x = x.reshape(-1,3)
_y = np.zeros_like(_x)
for i in xrange(_x.shape[0]):
    _y[i,:] = f(_x[i,:])
y = _y.reshape(x.shape)

compare that to what tensordot does: 将其与tensordot功能进行比较:

newshape_a = (-1, N2)
....
at = a.transpose(newaxes_a).reshape(newshape_a)
bt = b.transpose(newaxes_b).reshape(newshape_b)
res = dot(at, bt)
return res.reshape(olda + oldb)

Basically the same strategy. 基本上是相同的策略。 If it doesn't look sufficiently 'pythonic' you can hide the messy details in a function. 如果看起来不够“ pythonic”,则可以将杂乱的细节隐藏在函数中。 :) :)

This kind of reshaping is most useful when the underlying function can handle 2 dimensions, one active, and one that is passive, 'going along for the ride'. 当基础功能可以处理2个维度(一个是主动的,一个是被动的)时,这种重塑最有用。 Transpose can move the active axis to the front or back, depending on what's most convenient. 移调可以根据最方便的方式将活动轴前后移动。

Another strategy, used in apply_along_axis is to construct an indexing list: apply_along_axis使用的另一种策略是构造索引列表:

for i in range(N):
    fun(arr[tuple([slice(N),slice(N)...,i])]

I've answered similar questions in the past about nditer . 过去,我已经回答过有关nditer类似问题。 https://stackoverflow.com/a/28727290/901925 https://stackoverflow.com/a/28727290/901925

np.ndindex is a good example of using nditer to iterate over a subset of the axes. np.ndindex是使用nditer迭代轴子集的一个很好的例子。 Look at its code. 看一下它的代码。 Basically it constructs a dummy array of the right shape, and generates indices of the multi_index type. 基本上,它构造正确形状的虚拟数组,并生成multi_index类型的索引。

This is also illustrated at http://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#tracking-an-index-or-multi-index http://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#tracking-an-index-or-multi-index中也对此进行了说明

That indexing doc is the best description of nditer . 该索引文档是对nditer的最好描述。 Notice how it ends with an cython example. 请注意,它以cython示例结尾。 I think that's the best use of the Python nditer - as a stepping stone to using it in cython or c . 我认为这是Python nditer的最佳用法-作为在cythonc使用它的cython

In Python it can be useful as a way of iterating over several input and output arrays in a coordinated fashion, but it does not have any speed advantages. 在Python中,它可以用作以协调的方式遍历几个输入和输出数组的方式,但是它没有任何速度优势。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM