gpt4 book ai didi

python - 将函数应用于 ndarray 的 0 维

转载 作者:太空宇宙 更新时间:2023-11-03 11:23:30 25 4
gpt4 key购买 nike

问题

  • 我有一个 ndarray,由 arr 定义,它是一个 n 维立方体,长度为 m在每个维度。

  • 我想通过沿维度 n=0 切片并取每个 n-1 来执行函数 func -dim 切片作为函数的输入。

这似乎适用于 map() 但我找不到合适的 numpy 变体。 np.vectorise 似乎将 n-1 张量拆分为单独的标量条目。 apply_along_axisapply_over_axes 似乎也不合适。

我的问题是我需要将任意函数作为输入传递,所以我也没有看到使用 einsum 的解决方案是可行的。

问题

  • 您知道使用 np.asarray(map(func, arr)) 的最佳 numpy 替代方案吗?

例子

我通过以下方式将示例数组 arr 定义为 4-dim 立方体(或 4-tensor):

m, n = 3, 4 
arr = np.arange(m**n).reshape((m,)*n)

我定义了一个示例函数f,

def f(x):
"""makes it obvious how the np.ndarray is being passed into the function"""
try: # perform an op using x[0,0,0] which is expected to exist
i = x[0,0,0]
except:
print '\nno element x[0,0,0] in x: \n{}'.format(x)
return np.nan
return x-x+i

此函数的预期结果 res 将保持相同的形状,但会满足以下条件:

print all([(res[i] == i*m**(n-1)).all() for i in range(m)])

这适用于默认的 map() 函数,

res = np.asarray(map(f, a))
print all([(res[i] == i*m**(n-1)).all() for i in range(m)])
True

我希望 np.vectorize 以与 map() 相同的方式工作,但它在标量条目中起作用:

res = np.vectorize(f)(a)

no element x[0,0,0] in x:
0
...

最佳答案

假设 arr 是 4d,而你的 fn 适用于 3d 数组,

np.asarray(map(func, arr))   # list(map(...)) for Py3

看起来非常合理。我会使用列表理解形式,但这是编程风格的问题

np.asarray([func(i) for i in arr])

for i in arrarr 的第一个维度上迭代。实际上,它将 arr 视为 3d 数组的列表。然后它将结果列表重新组合成一个 4d 数组。

np.vectorize 文档可以更明确地说明采用标量的函数。但是,是的,它将值作为标量传递。请注意,np.vectorize 没有提供传递迭代轴参数的规定。当您的函数从多个数组中获取值时,它最有用,比如

 [func(a,b) for a,b in zip(arrA, arrB)]

它概括了 zip 以便进行广播。但除此之外,它是一个迭代解决方案。它对 func 的内部结构一无所知,因此无法加快调用速度。

np.vectorize 最终调用 np.frompyfunc,它不太通用但速度更快。但它也将标量传递给函数。

np.apply_along/over_ax(e/i)s 也迭代一个或多个轴。您可能会发现他们的代码很有启发性,但我同意他们不适用于此处。

map 方法的一个变体是分配结果数组和索引:

In [45]: res=np.zeros_like(arr,int)
In [46]: for i in range(arr.shape[0]):
...: res[i,...] = f(arr[i,...])

如果您需要在与第一个不同的轴上迭代,这可能会更容易。

您需要自己计时,看看哪个更快。

========================

在第一个维度上进行就地修改的迭代示例:

In [58]: arr.__array_interface__['data']  # data buffer address
Out[58]: (152720784, False)

In [59]: for i,a in enumerate(arr):
...: print(a.__array_interface__['data'])
...: a[0,0,:]=i
...:
(152720784, False) # address of the views (same buffer)
(152720892, False)
(152721000, False)

In [60]: arr
Out[60]:
array([[[[ 0, 0, 0],
[ 3, 4, 5],
[ 6, 7, 8]],

...

[[[ 1, 1, 1],
[30, 31, 32],
...

[[[ 2, 2, 2],
[57, 58, 59],
[60, 61, 62]],
...]]])

当我遍历一个数组时,我得到一个从公共(public)数据缓冲区上的连续点开始的 View 。如果我修改 View ,如上所述,甚至使用 a[:]=...,我修改了原始 View 。我不必写回任何东西。但不要使用 a = ....,这会破坏与原始数组的链接。

关于python - 将函数应用于 ndarray 的 0 维,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38335116/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com