【问题标题】:scipy.optimize.curve_fit, TypeError: unsupported operand typescipy.optimize.curve_fit,TypeError:不支持的操作数类型
【发布时间】:2012-12-26 10:24:50
【问题描述】:

我进行了搜索,问题似乎类似于Python scipy: unsupported operand type(s) for ** or pow(): 'list' and 'list' 但是那里发布的解决方案不起作用,我认为它实际上可能有所不同。

我正在尝试使用 scipy.curve_fit 将曲线拟合到数据中,当我将所有 3 个参数都留空时,一切正常,我得到了预期的结果。

def func(x,a,b,c):
  return a*np.exp(b*(x**c)) 

popt, pcov = curve_fit(func,x,y)

但是,当我尝试修复以下值之一 (c=2) 时,

def func2(x,a,b):
  return a*np.exp(b*(x**2))

popt, pcov = curve_fit(func2,x,y)

我得到TypeError: unsupported operand type(s) for ** or pow(): 'int' and 'list' 使用numpy.power(x,2) 链接问题中的建议允许代码运行但产生错误的结果。有人看到我做错了吗?

编辑添加: 更令人困惑的是,据我所知,它是由 curve_fit 使用的,第二个公式有效。

第二次编辑: 对于那些提到列表问题的人,X 和 Y 现在都是数组,并且代码运行没有错误。然而 func2 仍然会产生严重的错误结果。 (我会在这里发布图表,但显然我需要更多代表。)

Func 1 curvefit 给出了[a,b,c] = [ 1.71890826, -0.0239123, 3.17039851],但是对于 func2,这一切都出错了[a,b] = [ -2.88694423e-15, 9.99999998e-01]。我不明白这么小的变化怎么会导致这么严重的问题,leastsq 能够用 c=2 拟合这个数据。

【问题讨论】:

  • 你能提供xy的例子吗?

标签: python scipy typeerror curve-fitting


【解决方案1】:

TypeError 的出现是因为传递给 func2x 是一个列表。

这是一个例子:

import numpy as np
import scipy.optimize as optimize
def func2(x,a,b):
    return a*np.exp(b*(x**2))

x = np.linspace(0,1,6).reshape(2,-1)
y = func2(x,1,1)
x = x.tolist()
y = y.tolist()
print(x)
# [[0.0, 0.2, 0.4], [0.6000000000000001, 0.8, 1.0]]
print(y)
# [[1.0, 1.0408107741923882, 1.1735108709918103], [1.4333294145603404, 1.8964808793049517, 2.718281828459045]]

popt, pcov = optimize.curve_fit(func2, x, y)
# TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int'

在这种情况下,func2 将形状为 (2,3) 的数组 x 映射到形状为 (2,3) 的数组 y。函数optimize.curve_fit 期望来自func2 的返回值是一个数字序列——而不是一个数组。

对我们来说幸运的是,在这种情况下,func2x 的每个组件上按元素操作——x 的元素之间没有交互。因此,如果我们传递形状为 (2,3) 的数组 x 或形状为 (6,) 的一维数组,这真的没有什么区别。

如果我们传递一个形状为 (6,) 的数组,那么func2 将返回一个形状为 (6,) 的数组。完美的。这样就可以了:

x = np.asarray(x).ravel()
y = np.asarray(y).ravel()
popt, pcov = optimize.curve_fit(func2, x, y)
print(popt)
# [ 1.  1.]

【讨论】:

  • X 和 y 确实是列表,已转换为数组并再次运行(需要一段时间)。希望这会奏效,我不明白为什么第一个例子有效但第二个失败了。当然,如果数据是一个列表,那么它们都应该失败吗?
  • 我们这里有两个不同的东西,它们都被称为xx 作为参数传递给optimize.curve_fitx 传递给func2。前者(我猜)是一个列表。在这种情况下,后者将是一个数字列表。 (前x 中的每个项目一次传递给func2 一个)。 func2 在后者 x 是一个列表时引发 TypeError。
  • 代码现在在 X 和 Y 转换为数组后运行,但是 func2 不会产生正确的结果,两个函数都给出了相同的数据,我知道当 C=2 时,leastsq 能够拟合数据.我完全被这个困住了。
  • leastsq 要求您传递参数的初始猜测。您是否将相同的猜测传递给curve_fit
  • 啊,好吧,现在我觉得自己很愚蠢,不,我没有在 curve_fit 案例中提供初始案例,而我使用的是 leastsq。如果出现在 c=?它能够从 1 开始就到达那里,但在 c=2 的情况下是不同的。谢谢!
【解决方案2】:

您使用了哪些x 值?以下示例对我有用。

from scipy.optimize import curve_fit
import numpy as np

def func2(x,a,b):
  return a*np.exp(b*(x**2))

x = np.linspace(0,4,50)
y = func2(x, 2.5, 2.3)
yn = y + 6.*np.random.normal(size=len(x))
popt, pcov = curve_fit(func2,x,yn)
print popt, pcov

它根据random 函数给出结果:

[ 1.64182333  2.00134505] [[  1.77331612e+11  -6.77171181e+09]
 [ -6.77171181e+09   2.58627411e+08]]

您的xyn 值是列表类型吗?以下示例给出了您的错误消息:

print range(10)**2

TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int'

【讨论】:

  • X 和 y 确实是列表,已转换为数组并再次运行(需要一段时间)。希望这会奏效,我不明白为什么第一个例子有效但第二个失败了。当然,如果数据是一个列表是他们都应该失败的问题吗?
【解决方案3】:

Python 正在尝试做这样的事情:

[1, 2, 3] * 4

在 CPython 中没有定义 * 运算符。

这对我有用:

def second_order_polynomial(x, a, b, c):
    return [a * x0**2 + b * x0 + c for x0 in x]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-29
    • 2011-03-08
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 2018-04-27
    • 1970-01-01
    相关资源
    最近更新 更多