使用scipy.optimize.curve_fit不能正确拟合曲线

vuv7lop3  于 2023-05-17  发布在  其他
关注(0)|答案(1)|浏览(204)

我想将随机时间序列段拟合到预定义的函数列表中。出于演示目的,我只使用正弦函数和演示时间序列。

amplitude = 1
omega = 2
phase = 0.5
offset = 4

def sine(x, a, b, c, d):
  """Sine function"""
  return a*np.sin(b*x+c) + d

x = np.linspace(0,100, 1000)

parameters = [amplitude, omega, phase, offset]
demo_values = sine(x, *parameters)

正如标题中提到的,我使用scipy.optimize.curve_fit方法来尝试查找参数,如下所示:

from scipy.optimize import curve_fit

popt, err = curve_fit(f=sine, xdata=x, ydata=demo_values)

fitted = sine(x, *popt)

当比较曲线拟合的参数与原始参数时,我发现它们有很大的不同。我不知道我做错了什么。

print(f"Scipy params: {popt}")
print(f"Original params: {parameters}")
>>> Scipy params: [0.02834886 1.15624779 1.8580548  4.00011998]
>>> Original params: [1, 2, 0.5, 4]

注意:正如在引言中提到的,我不想只找到正弦函数的解决方案,因为我想将这个流程扩展到其他函数。我在SO上看到使用p0变量显著提高了准确性,但我不知道如何以通用的方式进行初始猜测(对于任何曲线)。
我尝试用scipy.optimize.curve_fit函数拟合一条简单的正弦曲线,并期望库能很好地处理这一问题。不幸的是,情况并非如此。我还看到其他与我的问题相关的帖子使用了p0(初始猜测)变量,我不知道如何创建通用曲线。

fgw7neuy

fgw7neuy1#

正如我在上面的评论中所写的,在拟合之前分析数据很重要。当函数是周期函数时,你不需要在不同的x值上有很多点。
分析可以指示数据是周期性的并且仅使用其一部分。

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

amplitude = 1
omega = 2
phase = 0.5
offset = 4

def sine(x, a, b, c, d):
  """Sine function"""
  return a*np.sin(b*x+c) + d

n = 30
xdata = np.linspace(0, 3, n)

parameters = [amplitude, omega, phase, offset]
demo_values = sine(xdata, *parameters)

absolute_max_noise = 0.05
noise = - absolute_max_noise + 2*absolute_max_noise*np.random.rand(n)
ydata = demo_values + noise

popt, err = curve_fit(f=sine, xdata=xdata, ydata=ydata)

# fitted line...
xline = np.linspace(xdata.min(), xdata.max(), 100)
yline = sine(xline, *popt)

print(f"Scipy params: {popt}")
print(f"Original params: {parameters}")

plt.plot(xdata, ydata, ls='', marker='x', label='data')
plt.plot(xline, yline, label='fit')
plt.legend()
plt.show()

Scipy params: [0.9848958  2.00426151 0.49902431 3.99979896]
Original params: [1, 2, 0.5, 4]

相关问题