首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >函数总是返回numpy数组。

函数总是返回numpy数组。
EN

Stack Overflow用户
提问于 2012-09-24 13:09:54
回答 4查看 4.4K关注 0票数 1

我遇到了一个what函数,它似乎返回一个numpy数组,不管传递给它什么。在我的应用程序中,我只需要能够传递标量和列表,因此唯一的“问题”是,当我将标量传递给函数时,会返回带有一个元素的数组(当我期望得到标量时)。我应该忽略这一行为,还是黑掉函数以确保在传递标量时返回标量?

示例代码:

代码语言:javascript
运行
复制
#! /usr/bin/env python

import scipy
import scipy.optimize
from numpy import cos

# This a some function we want to compute the inverse of
def f(x):
    y = x + 2*cos(x)
    return y

# Given y, this returns x such that f(x)=y
def f_inverse(y):

    # This will be zero if f(x)=y
    def minimize_this(x):
        return y-f(x)

    # A guess for the solution is required
    x_guess = y
    x_optimized = scipy.optimize.fsolve(minimize_this, x_guess) # THE PROBLEM COMES FROM HERE
    return x_optimized

# If I call f_inverse with a list, a numpy array is returned
print f_inverse([1.0, 2.0, 3.0])
print type( f_inverse([1.0, 2.0, 3.0]) )

# If I call f_inverse with a tuple, a numpy array is returned
print f_inverse((1.0, 2.0, 3.0))
print type( f_inverse((1.0, 2.0, 3.0)) )

# If I call f_inverse with a scalar, a numpy array is returned
print f_inverse(1.0)
print type( f_inverse(1.0) )

# This is the behaviour I expected (scalar passed, scalar returned).
# Adding [0] on the return value is a hackey solution (then thing would break if a list were actually passed).
print f_inverse(1.0)[0] # <- bad solution
print type( f_inverse(1.0)[0] )

在我的系统中,它的输出是:

代码语言:javascript
运行
复制
[ 2.23872989  1.10914418  4.1187546 ]
<type 'numpy.ndarray'>
[ 2.23872989  1.10914418  4.1187546 ]
<type 'numpy.ndarray'>
[ 2.23872989]
<type 'numpy.ndarray'>
2.23872989209
<type 'numpy.float64'>

我使用的是SciPy 0.10.1和MacPorts提供的Python2.7.3。

溶液

在阅读了下面的答案后,我确定了以下的解决方案。将f_inverse中的返回行替换为:

代码语言:javascript
运行
复制
if(type(y).__module__ == np.__name__):
    return x_optimized
else:
    return type(y)(x_optimized)

在这里,return type(y)(x_optimized)使返回类型与调用函数的类型相同。不幸的是,如果y是numpy类型,则这不起作用,因此if(type(y).__module__ == np.__name__)用于detect numpy types using the idea presented here并将它们排除在类型转换之外。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-09-24 13:21:05

scipy.optimize.fsolve中实现的第一行是:

x0 = array(x0, ndmin=1)

这意味着你的标量将变成一个1元素序列,而你的1元素序列将基本上保持不变。

这似乎是一个实现细节,我将重构您的代码,使其不允许将标量发送到fsolve。我知道这似乎有悖于鸭子类型,但函数要求为该参数提供一个ndarray,因此您应该尊重接口,以便对实现中的更改保持健壮。但是,我不认为有条件地使用x_guess = array(y, ndmin=1)将标量转换为包装器函数中的ndarray并在必要时将结果转换为标量没有任何问题。

下面是fsolve函数的docstring的相关部分:

x0,args=(),fprime=None,full_output=0,col_deriv=0,xtol=1.49012e-8,maxfev=0,band=None,epsfcn=0.0,factor=100,diag=None):“”找到函数的根。返回由func(x) = 0定义的(非线性)方程的根,给出一个起始估计.参数-函数:可调用的f(x,*args)函数,它至少包含一个(可能是向量)参数。x0 : ndarray -- func(x) = 0根的起始估计。-返回

票数 3
EN

Stack Overflow用户

发布于 2012-09-24 15:04:51

下面是如何将Numpy数组转换为列表并将Numpy标量转换为Python标量的方法:

代码语言:javascript
运行
复制
>>> x = np.float32(42)
>>> type(x)
<type 'numpy.float32'>
>>> x.tolist()
42.0

换句话说,tolist方法在np.ndarray上专门处理标量。

这仍然给您留下了单元素列表,但这些元素列表很容易以通常的方式处理。

票数 2
EN

Stack Overflow用户

发布于 2012-09-24 14:19:34

我想wims的回答其实已经说了很多,但也许这使得差别更清楚了。

numpy返回的标量应该与array[0]一起使用(几乎?)完全兼容标准python浮点:

代码语言:javascript
运行
复制
a = np.ones(2, dtype=float)
isinstance(a[0], float) == True # even this is true.

在大多数情况下,1大小的数组与标量和列表都是兼容的,不过,例如,它是一个可变对象,而浮点数不是:

代码语言:javascript
运行
复制
a = np.ones(1, dtype=float)
import math
math.exp(a) # works
# it is not isinstance though
isinstance(a, float) == False
# The 1-sized array works sometimes more like number:
bool(np.zeros(1)) == bool(np.asscalar(np.zeros(1)))
# While lists would be always True if they have more then one element.
bool([0]) != bool(np.zeros(1))

# And being in place might create confusion:
a = np.ones(1); c = a; c += 3
b = 1.; c = b; c += 3
a != b

因此,如果用户不应该知道它,我认为第一个是好的,第二个是危险的。

还可以使用np.asscalar(result)将大小为1的数组(任意维度)转换为正确的python标量:

29: type(np.asscalar(a)) Out29: float

如果您想确保不应该知道numpy的用户没有任何惊喜,那么如果一个标量被传入,您至少必须得到0的元素。如果用户应该了解numpy,那么仅仅是文档可能也一样好。

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

https://stackoverflow.com/questions/12565735

复制
相关文章

相似问题

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