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

正弦曲线拟合问题:拟合得到的振幅和频率远低于实际值

正弦曲线拟合温度时间序列失败问题解决方案

原始问题

data
我有一组时间序列数据,对应图中的黑线(为滑动均值结果)。我尝试对其进行正弦曲线拟合但未成功,当前拟合结果为接近直线的浅蓝线。(深蓝色为多项式拟合结果,可暂时忽略)。

我所尝试的方法如下:

def objective(x, a, b, c, d):
    return a * np.sin(b - x) + c * x**2 + d
from scipy import optimize

X = X.ravel() # 序数日期构成的一维数组
y = y.ravel() # 温度值构成的一维数组

# 使用目标函数进行曲线拟合
params, _ = optimize.curve_fit(objective, X, y)

# 绘制拟合曲线
plt.plot(X_extended, objective(
    X, params[0], params[1], params[2], params[3]))

即便我设置了极低频率或极高振幅的初始猜测值,拟合结果几乎没有变化。


解决方案

问题原因

你定义的目标函数存在两处核心缺陷导致拟合失败:

  1. 正弦项的角频率被固定为1,没有作为可拟合参数开放自由度,无法匹配温度序列的年/季度周期特征
  2. 非线性拟合对初始参数值敏感度极高,你未传入符合数据特征的初始值,默认的全1初始值直接导致拟合陷入局部最优

修改方案

1. 调整目标函数,增加角频率参数

import numpy as np
def objective(x, a, omega, phi, c, d):
    # 参数说明:a为正弦振幅,omega为角频率,phi为相位,c为二次项系数,d为全局偏移量
    return a * np.sin(omega * x + phi) + c * x**2 + d

如果你的数据没有明显的二次趋势,也可以将二次项替换为线性项k*x,进一步降低拟合难度。

2. 传入合理初始参数值

根据温度序列的常规特征设置初始值,以日度序列的年周期为例:

from scipy import optimize

X = X.ravel()
y = y.ravel()

# 初始值可根据你的数据实际范围调整,以下为通用参考值
p0 = [
    10, # 温度年波动振幅约为±10℃,可根据你的数据极差调整
    2*np.pi/365, # 年周期对应的角频率,若为月度数据则改为2*np.pi/12
    0, # 相位初始值
    1e-8, # 二次趋势项系数,若改为线性项可设为1e-5量级
    np.mean(y) # 全局偏移量直接用温度均值初始化
]

params, _ = optimize.curve_fit(objective, X, y, p0=p0)

# 绘制拟合曲线时注意传入扩展后的X序列
plt.plot(X_extended, objective(X_extended, *params))

效果验证

按上述方案调整后即可得到符合预期的拟合结果:
newly fitted function

可选优化

如果你的数据存在多周期特征(比如年周期叠加周周期),可以叠加多个正弦项分别设置对应频率的初始值,拟合效果会更优。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 07:09:02