首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用numpy数组对象的numpy数组执行numpy函数?

如何使用numpy数组对象的numpy数组执行numpy函数?
EN

Stack Overflow用户
提问于 2018-02-18 23:14:14
回答 1查看 482关注 0票数 0

假设我们有一个用于创建numpy数组对象的numpy数组的函数:

代码语言:javascript
复制
randarr = lambda shape: np.random.randint(0, 10, shape)
get_numpy_array_obj = lambda shapes: \
    np.array([randarr(shape) for shape in shapes])

以及数组的定义大小:

代码语言:javascript
复制
shapes = [(2, 3), (3, 4), (4, 2)]

由于数组的形状不同,numpy将其他数组视为对象。

现在,如果我们创建两个这样的数组

代码语言:javascript
复制
A = get_numpy_array_obj(shapes)
B = get_numpy_array_obj(shapes)

做简单的操作,如+,-,**等不是问题,例如:

代码语言:javascript
复制
C = A * B - (A + B)**2

当我想在tanh,exp等数组上应用numpy函数时,问题就出现了。

代码语言:javascript
复制
D = np.tanh(A)

这将向我返回以下错误:

代码语言:javascript
复制
AttributeError: 'numpy.ndarray' object has no attribute 'tanh'

我可以对每个数组逐个应用函数,如下所示

代码语言:javascript
复制
D = np.array([np.tanh(a) for a in A])

我的想法是写更少的代码和更多的可读性。

此外,np.vectorize(np.tanh)(A)也无法正常工作。这将返回:

代码语言:javascript
复制
ValueError: setting an array element with a sequence.

是否有其他可能的方法将numpy函数应用于numpy数组对象的数组?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-19 00:34:40

代码语言:javascript
复制
In [99]: arr = np.array([np.ones(ij) for ij in [(1,3),(2,4),(3,2)]])
In [100]: arr
Out[100]: 
array([array([[1., 1., 1.]]),
       array([[1., 1., 1., 1.],
       [1., 1., 1., 1.]]),
       array([[1., 1.],
       [1., 1.],
       [1., 1.]])], dtype=object)

像'+‘这样的运算符之所以有效,是因为数组有相应的方法:

代码语言:javascript
复制
In [101]: arr[0].__add__
Out[101]: <method-wrapper '__add__' of numpy.ndarray object at 0xb64897a0>
In [102]: arr+arr
Out[102]: 
array([array([[2., 2., 2.]]),
       array([[2., 2., 2., 2.],
       [2., 2., 2., 2.]]),
       array([[2., 2.],
       [2., 2.],
       [2., 2.]])], dtype=object)

但是像np.tanh这样的函数没有数组方法。

frompyfunc将数组的元素传递给您的函数并返回一个对象数据类型数组。通常这很痛苦,但在这种情况下,这正是我们想要的:

代码语言:javascript
复制
In [103]: np.frompyfunc(np.tan,1,1)(arr)
Out[103]: 
array([array([[1.55740772, 1.55740772, 1.55740772]]),
       array([[1.55740772, 1.55740772, 1.55740772, 1.55740772],
       [1.55740772, 1.55740772, 1.55740772, 1.55740772]]),
       array([[1.55740772, 1.55740772],
       [1.55740772, 1.55740772],
       [1.55740772, 1.55740772]])], dtype=object)

vectorize也使用frompyfunc,但会尝试将结果转换为数字数组。我们可以通过指定一个otypes跳过这一步

代码语言:javascript
复制
In [104]: np.vectorize(np.tan,otypes='O')(arr)
Out[104]: 
array([array([[1.55740772, 1.55740772, 1.55740772]]),
       array([[1.55740772, 1.55740772, 1.55740772, 1.55740772],
       [1.55740772, 1.55740772, 1.55740772, 1.55740772]]),
       array([[1.55740772, 1.55740772],
       [1.55740772, 1.55740772],
       [1.55740772, 1.55740772]])], dtype=object)

对象数组迭代在速度上介于列表迭代和数值数组迭代之间。它有一些数组开销,但不是全部。元素是指针,就像在列表中一样。

frompyfunc可以比显式迭代快一点(高达2倍)。vectorize比较慢,因为它有一些开销。这些函数的最大优点是它们可以处理广播。做你自己的计时,看看它们是否有帮助。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48853179

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档