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

Python中正弦曲线拟合:如何为给定数据集拟合单峰正弦曲线

单峰正弦曲线拟合问题解决

数据集

xData = np.array([1.7, 8.8, 15, 25, 35, 45, 54.8, 60, 64.7, 70])
yData = np.array([30, 20, 13.2, 6.2, 3.9, 5.2, 10, 14.8, 20, 27.5])

问题描述

你已成功用scipy.optimize.curve_fit拟合抛物线,但正弦曲线拟合效果不佳,当前尝试代码及运行结果如下:

当前尝试代码

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

xData = np.array([1.7, 8.8, 15, 25, 35, 45, 54.8, 60, 64.7, 70])
yData = np.array([30, 20, 13.2, 6.2, 3.9, 5.2, 10, 14.8, 20, 27.5])


def model_parabola(x, a, b, c):
    return a * (x - b) ** 2 + c


def model_sine(x, amp, omega, phase, c, z):
    return amp * np.sin(omega * (x - z) + phase) + c


poptsin, pcovsine = curve_fit(model_sine, xData, yData, p0=[np.std(yData) *2 **0.5, 2 * np.pi, 0, np.mean(yData), 0])
popt, pcov = curve_fit(model_parabola, xData, yData, p0=[2, 3, 4])

# 抛物线拟合结果
aopt, bopt, copt = popt
xmodel = np.linspace(min(xData), max(xData), 100)
ymodel = model_parabola(xmodel, aopt, bopt, copt)

print(poptsin)
# 正弦曲线拟合结果
ampopt, omegaopt, phaseopt, ccopt, zopt = poptsin
xSinModel = np.linspace(min(xData), max(xData), 100)
ySinModel = model_sine(xSinModel, ampopt, omegaopt, phaseopt, ccopt, zopt)

y_fit = model_sine(xSinModel, *poptsin)

plt.scatter(xData, yData)
plt.plot(xmodel, ymodel, 'r-')
plt.plot(xSinModel, ySinModel, 'g-')

plt.show()

当前运行结果

拟合结果图

问题原因

正弦曲线拟合失败的核心问题有两个:

  1. 初始参数p0设置严重不合理:你设置的omega为2*np.pi,会导致正弦曲线在x的小范围内振荡数十次,完全不符合数据的单峰趋势。
  2. 模型参数冗余:omega*(x-z)+phase可合并为omega*x + (phase - omega*z),多余的参数z会增加拟合不确定性,导致算法难以收敛到合理结果。

修正方案

1. 简化正弦模型

去掉冗余参数,降低拟合难度:

def model_sine(x, amp, omega, phase, offset):
    return amp * np.sin(omega * x + phase) + offset

2. 设置合理初始参数

根据数据特征估算初始值:

  • amp(振幅):数据最大值30,最小值3.9,振幅约为(30-3.9)/2 ≈13
  • omega(角频率):x范围1.7~70,数据呈现波峰到波峰的趋势,周期约为140,因此omega=2*np.pi/140≈0.045
  • phase(相位):波谷在x≈35处,此时sin(omega*x + phase)=-1,计算得phase≈3*np.pi/2 - 0.045*35≈3.14
  • offset(偏移量):数据平均值约为15

修正后完整代码

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

xData = np.array([1.7, 8.8, 15, 25, 35, 45, 54.8, 60, 64.7, 70])
yData = np.array([30, 20, 13.2, 6.2, 3.9, 5.2, 10, 14.8, 20, 27.5])


def model_parabola(x, a, b, c):
    return a * (x - b) ** 2 + c


# 简化后的正弦模型
def model_sine(x, amp, omega, phase, offset):
    return amp * np.sin(omega * x + phase) + offset


# 抛物线拟合(保留原逻辑)
popt, pcov = curve_fit(model_parabola, xData, yData, p0=[2, 3, 4])
aopt, bopt, copt = popt
xmodel = np.linspace(min(xData), max(xData), 100)
ymodel = model_parabola(xmodel, aopt, bopt, copt)

# 设置合理初始参数后拟合正弦曲线
p0_sin = [13, 0.045, 3.14, 15]
poptsin, pcovsine = curve_fit(model_sine, xData, yData, p0=p0_sin)

# 生成正弦拟合曲线
xSinModel = np.linspace(min(xData), max(xData), 100)
ySinModel = model_sine(xSinModel, *poptsin)

# 绘图并添加图例
plt.scatter(xData, yData, label='原始数据')
plt.plot(xmodel, ymodel, 'r-', label='抛物线拟合')
plt.plot(xSinModel, ySinModel, 'g-', label='正弦曲线拟合')
plt.legend()
plt.show()

# 打印拟合参数
print("正弦曲线拟合参数:", poptsin)

修正后效果

修正后的正弦曲线会紧密贴合原始数据的单峰趋势,拟合效果与抛物线接近,且符合正弦曲线的数学特征。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 07:55:19