You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化scipy curve_fit的正弦函数曲线拟合效果?

如何优化正弦函数对测点数据的拟合效果

尝试用正弦函数拟合一组测点数据,拟合效果不理想,调整curve_fit参数也无法改善,可通过以下方案优化:

原始代码与拟合问题

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

xdata = np.array([0.  , 0.02, 0.04, 0.06, 0.08, 0.1 , 0.12, 0.14, 0.16, 0.18, 0.2 ,
       0.22, 0.24, 0.26, 0.28, 0.3 , 0.32, 0.34, 0.36, 0.38, 0.4 , 0.42,
       0.44, 0.46, 0.48, 0.5 , 0.52, 0.54, 0.56, 0.58, 0.6 , 0.62, 0.64,
       0.66, 0.68, 0.7 , 0.72, 0.74, 0.76, 0.78, 0.8 , 0.82, 0.84, 0.86,
       0.88, 0.9 , 0.92, 0.94, 0.96, 0.98, 1.  , 1.02, 1.04, 1.06, 1.08,
       1.1 , 1.12])
ydata = np.array([37.5, 36.4, 37.1, 37.3, 38.2, 38.4, 38.1, 36.7, 34.3, 32.2, 33.1,
       31.8, 33.4, 35.7, 37.8, 38.3, 38.1, 37. , 34.9, 32.5, 31.6, 31.7,
       33.5, 35.5, 37.8, 38.4, 38.3, 36.9, 34.8, 32.2, 33.9, 31.6, 33.3,
       35.5, 37.6, 38.3, 38.2, 36.7, 34.8, 32.4, 31.5, 32.1, 33.3, 35.5,
       37.2, 38.3, 38.3, 36.8, 34.5, 32.3, 31.6, 31.8, 33.3, 35.7, 37.8,
       38.4, 38.2])


def sin_fun(x,a,b,c,d):
    return a*np.sin(b*x+c)+d

p_opt,p_cov=cf(sin_fun,xdata,ydata )
print(p_opt)
 
plt.plot(xdata,sin_fun(xdata,*p_opt))
plt.plot(xdata,ydata, 'r')
plt.show()

原始拟合效果示意图

问题根源

curve_fit默认使用全1的初始参数猜测,对于正弦函数拟合极易陷入局部最优解——尤其是当数据的周期、振幅、基线均值与1偏差较大时。你的数据呈现明显周期性波动,核心问题是未提供合理的初始拟合参数。

优化方案

1. 基于数据特征计算初始参数

通过数据的统计特征估算初始参数,让拟合从接近最优解的位置开始迭代:

  • 偏移量d:取数据的均值(正弦函数的基线)
  • 振幅a:取数据最大值与最小值差值的一半
  • 角频率b:观察数据周期,你的数据在x∈[0,0.4]完成一个周期,因此周期T≈0.4,角频率b=2π/T≈15.7
  • 相位c:先设为0,后续由拟合迭代优化

2. 带初始参数的拟合代码

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

xdata = np.array([0.  , 0.02, 0.04, 0.06, 0.08, 0.1 , 0.12, 0.14, 0.16, 0.18, 0.2 ,
       0.22, 0.24, 0.26, 0.28, 0.3 , 0.32, 0.34, 0.36, 0.38, 0.4 , 0.42,
       0.44, 0.46, 0.48, 0.5 , 0.52, 0.54, 0.56, 0.58, 0.6 , 0.62, 0.64,
       0.66, 0.68, 0.7 , 0.72, 0.74, 0.76, 0.78, 0.8 , 0.82, 0.84, 0.86,
       0.88, 0.9 , 0.92, 0.94, 0.96, 0.98, 1.  , 1.02, 1.04, 1.06, 1.08,
       1.1 , 1.12])
ydata = np.array([37.5, 36.4, 37.1, 37.3, 38.2, 38.4, 38.1, 36.7, 34.3, 32.2, 33.1,
       31.8, 33.4, 35.7, 37.8, 38.3, 38.1, 37. , 34.9, 32.5, 31.6, 31.7,
       33.5, 35.5, 37.8, 38.4, 38.3, 36.9, 34.8, 32.2, 33.9, 31.6, 33.3,
       35.5, 37.6, 38.3, 38.2, 36.7, 34.8, 32.4, 31.5, 32.1, 33.3, 35.5,
       37.2, 38.3, 38.3, 36.8, 34.5, 32.3, 31.6, 31.8, 33.3, 35.7, 37.8,
       38.4, 38.2])

def sin_fun(x,a,b,c,d):
    return a*np.sin(b*x+c)+d

# 计算初始参数
d_init = np.mean(ydata)
a_init = (np.max(ydata) - np.min(ydata)) / 2
b_init = 2 * np.pi / 0.4  # 周期T≈0.4
c_init = 0

p0 = [a_init, b_init, c_init, d_init]
p_opt, p_cov = cf(sin_fun, xdata, ydata, p0=p0)
print("优化后的参数:", p_opt)

plt.plot(xdata, sin_fun(xdata, *p_opt), label='拟合曲线')
plt.plot(xdata, ydata, 'r.', label='原始数据')
plt.legend()
plt.show()

3. 额外优化方向

  • 若单正弦函数仍无法完美拟合,可尝试叠加多阶谐波,比如使用a1*sin(b*x+c1) + a2*sin(2*b*x+c2) + d的形式,注意同步提供对应初始参数
  • 若数据含噪声,可给curve_fit传入sigma参数指定数据点权重,或使用method='trf'(Trust Region Reflective)方法,提升拟合稳健性

内容的提问来源于stack exchange,提问作者rpapa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 02:07:06