【问题标题】:scipy curve_fit doesn't work wellscipy curve_fit 效果不佳
【发布时间】:2018-06-07 06:50:33
【问题描述】:

我正在尝试使用以下代码拟合一些数据:

import numpy as np
import scipy.optimize
import matplotlib.pyplot as plt

def fseries(x, a0, a1, b1, w):
    f = a0 + (a1 * np.cos(w * x)) + (b1 * np.sin(w * x))
    return f

x = np.arange(0, 10)
y = [-45.0, -17.0, -33.0,  50.0, 48.0,  -3.0,  -1.0,   2.0,  84.0, 71.0]

res = scipy.optimize.curve_fit(fseries, x, y, maxfev=10000)

xt = np.linspace(0, 10, 100)
yt = fseries(xt, res[0][0], res[0][1], res[0][2], res[0][3])

plt.plot(x,y)
plt.plot(xt, yt, 'r')
plt.show()

这使得这个情节:

对我不理解或做错了什么有什么想法?

【问题讨论】:

  • 它并没有那么糟糕,只是你在每个系列中的样本数量严重不匹配,即 n=10 与 n=100 相比,所以当 n=100 时你有更多的空白填充

标签: python-3.x scipy curve-fitting


【解决方案1】:

首先,曲线拟合并不是为任何给定数据集创建良好曲线的神奇设备。您不能很好地将指数曲线拟合到对数数据集。如果您查看您的数据,您定义的函数是否很好地描述了它?它不是看起来像一个线性函数和一个正弦函数的叠加吗?
那么曲线拟合是一个迭代过程,它高度依赖于起始值。来自scipy manual

p0 : 无、标量或 N 长度序列,可选 参数的初始猜测。如果None,那么初始值都是1

为什么不为p0 提供更好的猜测?
最后但并非最不重要的一点是,您会返回两个数组。我会读两个,即使你只需要一个。它简化了您的代码。 试试

p0 = (10, 20, 20, 1.5)
res, _popcv = scipy.optimize.curve_fit(fseries, x, y, p0, maxfev=10000)
xt = np.linspace(0, 10, 100)
yt = fseries(xt, *res)

你已经变得更合适了。
当您定义更好的拟合函数时,您可以进一步提高拟合

def fseries(x, a0, a1, b1, w):
    f = a0 * x + (a1 * np.cos(w * x)) + (b1 * np.sin(w * x))
    return f

此功能是否有用,您必须决定。仅仅因为它更适合数据集,并不意味着它是适合您情况的描述符。

【讨论】:

  • 如何确定合理的初始猜测? p0 值似乎与 y 值无关。
  • p0 是您定义的函数fseries 的变量的初始猜测。在这种情况下,它包含 a0, a1, b1, w - 与您从 res 中的拟合算法返回的列表相同。
  • 我有一个使用 scipy 现有的 scipy.optimize.differential_evolution 遗传算法模块的例子来确定在bitbucket.org/zunzuncode/ramanspectroscopyfit 处将双洛伦兹峰方程拟合到碳纳米管的拉曼光谱的初始参数 - 这个 scipy 模块使用拉丁超立方算法来确保对参数空间的彻底搜索,并且它需要在其中搜索的参数范围,但是这些范围可能非常大。
猜你喜欢
  • 2015-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-25
  • 1970-01-01
  • 2014-09-05
  • 1970-01-01
  • 2016-04-22
相关资源
最近更新 更多