You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

为何scipy.optimize.curve_fit无法拟合numpy.sinc生成的数据?

解决scipy.optimize.curve_fit拟合numpy.sinc数据失败的问题

嘿,我太懂这种明明跟着文档走却拟合失败的挫败感了!你的问题大概率是**curve_fit默认的初始参数猜测和真实值差距太大**,导致优化器找不到正确的收敛方向。咱们来一步步修复:

1. 给拟合器一个靠谱的初始参数猜测

curve_fit默认会用[1, 1, 1]作为初始参数猜测,但你的真实参数是a=100h=3k=1,这俩差距实在太大了,优化器很容易在错误的区域打转。解决办法就是手动指定p0参数,给它一个接近真实值的起点:

# 用p0指定初始猜测,比如接近真实值的[90, 2, 1]
popt, pcov = curve_fit(func, xdata, ydata, p0=[90, 2, 1])

2. 注意numpy.sinc的定义(容易踩的隐形坑)

虽然你生成和拟合用的都是np.sinc,但还是要提一句:numpy的sinc(x)是**sin(πx)/(πx)**,而有些教材或工具里的sinc定义是sin(x)/x。如果以后你换了不同定义的sinc函数,拟合肯定会出问题,这点要记牢。

3. 调整噪声让拟合更稳定

你加的噪声均值是3,这会让你的数据整体上移,而真实的基线k=1,这种偏移会干扰拟合器对k的判断。要么把噪声均值改成0(更贴合真实数据的噪声情况),要么在初始猜测里把k设得更接近噪声偏移后的数值:

# 把噪声均值改为0,避免额外的基线偏移
y_noise = np.random.normal(0, 2, len(xdata))

修改后的完整代码

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

xdata = np.arange(-10, 10, 0.1)
y = 100*np.sinc(xdata - 3) + 1
# 调整噪声均值为0,减少基线干扰
y_noise = np.random.normal(0, 2, len(xdata))
ydata = y + y_noise

def func(x, a, h, k):
    return(a*np.sinc(x - h) + k)

# 指定初始参数猜测,让拟合器更快找到正确方向
popt, pcov = curve_fit(func, xdata, ydata, p0=[90, 2, 1])

# 绘图验证结果
plt.scatter(xdata, ydata, label='Noisy Data', s=5, alpha=0.6)
plt.plot(xdata, func(xdata, *popt), 'r-', linewidth=2, label='Fitted Curve')
plt.plot(xdata, y, 'g--', linewidth=2, label='True Curve')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()

# 打印拟合参数
print(f"拟合得到的参数:a={popt[0]:.2f}, h={popt[1]:.2f}, k={popt[2]:.2f}")

如果还是遇到拟合不收敛的情况,可以试试增加maxfev参数,给优化器更多迭代次数,比如:

popt, pcov = curve_fit(func, xdata, ydata, p0=[90, 2, 1], maxfev=10000)

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

火山引擎 最新活动