scipy curve_fit 效果不佳
scipy curve_fit doesn't work well
我正在尝试使用以下代码拟合一些数据:
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()
这使得这个情节:
对我不理解或做错的事情有什么想法吗?
首先,曲线拟合并不是一种可以为任何给定数据集创建良好曲线的神奇装置。您无法将指数曲线很好地拟合到对数数据集。如果您查看您的数据,您定义的函数是否很好地描述了它?它看起来不像是线性函数和正弦函数的叠加吗?
然后曲线拟合是一个迭代过程,高度依赖于起始值。来自 scipy manual:
p0 : None, scalar, or N-length sequence, optional
Initial guess for the parameters. If None, then the initial values will all be 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
这个功能有没有用,你自己判断吧。仅仅因为它更适合数据集,并不意味着它是您所处情况的正确描述符。
我正在尝试使用以下代码拟合一些数据:
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()
这使得这个情节:
对我不理解或做错的事情有什么想法吗?
首先,曲线拟合并不是一种可以为任何给定数据集创建良好曲线的神奇装置。您无法将指数曲线很好地拟合到对数数据集。如果您查看您的数据,您定义的函数是否很好地描述了它?它看起来不像是线性函数和正弦函数的叠加吗?
然后曲线拟合是一个迭代过程,高度依赖于起始值。来自 scipy manual:
p0 : None, scalar, or N-length sequence, optional Initial guess for the parameters. If None, then the initial values will all be 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
这个功能有没有用,你自己判断吧。仅仅因为它更适合数据集,并不意味着它是您所处情况的正确描述符。