为何scipy.optimize.curve_fit无法拟合正弦特性数据?
解决scipy.optimize.curve_fit拟合正弦曲线失败的问题
你的拟合失败核心原因是初始参数猜测(p0)与真实值偏差过大,尤其是正弦函数的角频率参数b,导致优化算法陷入局部最小值,无法收敛到正确结果。
步骤分析与修正:
d:数据的均值,你的数据在0.38~0.52之间,取0.45是合理的;a:振幅,(最大值-最小值)/2≈(0.52-0.38)/2=0.07;b:角频率,通过数数据周期估算:x从0到10约有8个完整周期,周期T≈10/8=1.25,因此b=2π/T≈5.03;c:相位,取第一个峰值位置x≈0.35,当cos(bx+c)=1时,c=-b*x≈-5*0.35=-1.75。
修正后的代码
from scipy.optimize import curve_fit as cf import numpy as np from matplotlib import pyplot as plt xdata = np.arange(0.05, 10.01, 0.05) ydata = """ 0.4000752 0.4231248 0.4456256 0.4684008 0.4892552 0.5054448 0.5150488 0.5155976 0.5081888 0.4919992 0.4716936 0.4494672 0.4258688 0.4058376 0.3901968 0.3803184 0.3794952 0.3866296 0.400624 0.4201064 0.4428816 0.4656568 0.4873344 0.5032496 0.5120304 0.513128 0.5070912 0.492548 0.4730656 0.4522112 0.4297104 0.4085816 0.3926664 0.3866296 0.3825136 0.3885504 0.4030936 0.4228504 0.4448024 0.4656568 0.48706 0.5029752 0.5120304 0.5134024 0.5068168 0.4928224 0.47334 0.4502904 0.4269664 0.4063864 0.3904712 0.3811416 0.3797696 0.3866296 0.4000752 0.4203808 0.4434304 0.4662056 0.4895296 0.5057192 0.518616 0.5191648 0.5101096 0.4988592 0.5005056 0.460992 0.4310824 0.4096792 0.3934896 0.3808672 0.380044 0.3866296 0.4000752 0.4201064 0.4428816 0.4659312 0.4865112 0.5024264 0.5114816 0.513128 0.5068168 0.4933712 0.4738888 0.4519368 0.4288872 0.4072096 0.3912944 0.385532 0.3797696 0.3888248 0.4058376 0.42532 0.444528 0.4673032 0.4919992 0.50764 0.513128 0.5128536 0.5059936 0.4950176 0.4771816 0.4511136 0.4286128 0.407484 0.3912944 0.3819648 0.380044 0.3860808 0.3998008 0.4190088 0.4415096 0.4648336 0.4851392 0.5013288 0.5112072 0.5128536 0.5125792 0.4922736 0.47334 0.4533088 0.4305336 0.4099536 0.393764 0.381416 0.3792208 0.385532 0.3989776 0.4190088 0.4409608 0.4640104 0.4854136 0.502152 0.5112072 0.513128 0.5068168 0.492548 0.4736144 0.4516624 0.4291616 0.4077584 0.3921176 0.382788 0.3803184 0.3863552 0.4000752 0.4179112 0.4406864 0.4634616 0.4865112 0.5029752 0.5125792 0.5142256 0.5081888 0.4947432 0.4736144 0.4519368 0.4286128 0.407484 0.3918432 0.3822392 0.3803184 0.3860808 0.3998008 0.4181856 0.440412 0.4634616 0.4837672 0.5002312 0.510384 0.5128536 0.5065424 0.4933712 0.4752608 0.4522112 0.4297104 0.4080328 0.3912944 0.381416 0.3794952 0.3880016 0.3987032 0.4179112 0.4420584 0.4626384 0.4832184 0.499408 0.5125792 0.5128536 0.506268 0.4933712 0.4749864 0.45276 0.4297104 0.4091304 0.3926664 0.382788 0.3808672 0.3866296 0.3998008 0.41846 """ ydata = [float(_) for _ in ydata.strip().splitlines()] def sin_fun(x,a,b,c,d): return a*np.cos(b*x+c)+d # 使用修正后的初始参数 p_opt, p_cov = cf(sin_fun, xdata, ydata, p0=(0.07, 5, -1.75, 0.45), method='trf') print("拟合参数:", p_opt) plt.plot(xdata, sin_fun(xdata, *p_opt), label='拟合曲线') plt.plot(xdata, ydata, 'r.-', ms=1, label='原始数据') plt.legend() plt.show()
结果说明
修正初始参数后,curve_fit会收敛到正确的参数值,拟合曲线将与原始数据高度匹配。如果需要更精准的结果,还可以基于第一次拟合的参数再次微调p0,进行二次拟合。
内容的提问来源于stack exchange,提问作者StarDust
相关产品推荐
相关产品推荐

