Python 中的简单余弦拟合失败

问题描述

以下是我生成数据和试穿的方法

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

def f(t,a,b):
    return a*np.cos(b*t)

v = 0 
x = 0.03

t = 0
dt = 0.001

time = []
pos = []

while t<3:
    a = (-5*x)/0.1
    v = v + a*dt
    x = x + v*dt
    time.append(t)
    pos.append(x)
    t = t+dt

pop,pcov = optimize.curve_fit(f,time,pos)
print(pop)

即使我为参数指定了初始值(例如“a”为 0.03,b 为“7”),结果拟合仍然很差(见下文,虚线是拟合函数)。

enter image description here

感谢您的任何提示

解决方法

正如 Tyberius 所指出的,您需要提供更好的初始值。 这是为什么? optimize.curve_fit 使用 least_squares 找到成本函数的局部最小值。 我相信在您的情况下,您陷入了这样一个局部最小值(这不是全局最小值)。如果您查看图表,您的拟合度约为 y=0。 (它有点波浪,因为它是余弦) 如果您稍微增加 a,误差会增加,因此 a 保持接近于零。如果您要增加 b 以适应数据的频率,成本函数也会上升,从而保持较低的值。

如果您不提供初始值,则每个参数都从 1 开始,如下所示:

plt.plot(time,pos,'black',label="data")
a,b = 1,1
init = [a*np.cos(b*t) for t in time]
plt.plot(time,init,'b',label="a,b=1,1")
plt.legend()
plt.show()

enter image description here

a 会下降,而 b 会留在后面。我相信规模是一个额外的问题。如果您将数据标准化为幅度为 1,则驼峰可能更明显且更易于拟合。 如果您从一个方便的 a 值开始,b 可以从低至 5 的初始值找到它的方式:

plt.plot(time,label="data")
for i in [1,4.8,4.9,5]:
    pop,pcov = optimize.curve_fit(f,time,p0=(0.035,i))
    a,b = pop
    fit = [a*np.cos(b*t) for t in time]
    plt.plot(time,fit,label=f"$b_0 = {i}$")

plt.legend()
plt.show()

enter image description here