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

Scipy(Python JupyterLab环境)下实验数据无法拟合至指定函数的求助

Scipy(Python JupyterLab环境)下实验数据无法拟合至指定函数的求助

嗨,各位大佬!我最近在处理一组实验数据的拟合问题,教授给了一个固定的拟合函数,但不管用scipy.optimize.curve_fit还是lmfit,拟合效果都很差,实在搞不懂哪里出问题了,想请大家帮忙看看。

我需要把下面的实验数据拟合到教授指定的函数里,函数形式不能改。其中RLC电路的电阻(R_tot-R_G)、电感L、电容C都是用专门设备实测得到的,理论上只有振幅参数A是未知的,但拟合出来的结果完全不对,残差也很不理想。

以下是我用到的完整代码和实验数据:

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

# 实验数据
x1 = np.array([200.  , 220.  , 240.  , 260.  , 280.  , 300.  , 320.  , 340.  ,
               360.  , 380.  , 390.  , 392.5 , 395.  , 397.5 , 400.  , 402.5 ,
               405.  , 407.5 , 410.  , 411.25, 412.5 , 413.75, 414.  , 415.25,
               416.5 , 417.75, 418.5 , 420.  , 422.5 , 425.  , 427.5 , 430.  ,
               432.5 , 435.  , 437.5 , 440.  , 450.  , 460.  , 480.  , 500.  ,
               510.  , 520.  , 540.  , 560.  , 570.  , 580.  , 600.  ])

y1 = np.array([0.00787402, 0.00904762, 0.01079365, 0.01269841, 0.01539683,
               0.01857143, 0.02321429, 0.0302    , 0.04303279, 0.06767896,
               0.09456265, 0.10338983, 0.11410579, 0.12545932, 0.14700855,
               0.16944444, 0.19692833, 0.22965779, 0.27434783, 0.28681818,
               0.32079208, 0.32562814, 0.32893401, 0.33061224, 0.32727273,
               0.31268293, 0.30236967, 0.28940092, 0.24274194, 0.20989011,
               0.18052805, 0.15531915, 0.13259053, 0.11627907, 0.10341463,
               0.07345133, 0.07455357, 0.06403509, 0.04163265, 0.03811475,
               0.02948207, 0.0272    , 0.02301587, 0.02027559, 0.01968254,
               0.01795276, 0.01672584])

σ_y1 = np.array([0.00021564, 0.00023222, 0.00025707, 0.00028599, 0.00032924,
                 0.00038243, 0.00046297, 0.00058876, 0.0008021 , 0.00127062,
                 0.00180749, 0.00196919, 0.00217276, 0.00239208, 0.00284333,
                 0.00317296, 0.00368032, 0.00432658, 0.00507593, 0.00532676,
                 0.0060111 , 0.00611128, 0.00618   , 0.00621495, 0.00607953,
                 0.0057964 , 0.0056074 , 0.00536185, 0.00463023, 0.00401191,
                 0.00347255, 0.00303842, 0.00250275, 0.00219007, 0.00196289,
                 0.0014738 , 0.00139797, 0.00129955, 0.00077378, 0.00082702,
                 0.00054713, 0.00053481, 0.00043752, 0.00041071, 0.0003831 ,
                 0.00037095, 0.00033556])

# 教授指定的拟合函数
def fitfunc1(x, A, R, L, C): # 频率f单位为kHz
    ω = 2*np.pi*x
    δ = R/(2*L)
    Ω = 1/sqrt(L*C)
    return A*ω/sqrt(ω**4-2*ω**2*(Ω**2-2*δ**2)+Ω**4)

# 实测的电路参数
R_tot = 77.54
R_G = 48
L = 308*1E-6
C = 508*1E-9

# 参数初始值:只有A是未知,其余为实测值
p_init1 = [31454, R_tot-R_G, L, C]

# 执行拟合
p_best1, cov1 = curve_fit(
    fitfunc1, x1, y1,          
    sigma=σ_y1,                 
    p0=p_init1, bounds=(0, +np.inf)  
)

# 残差计算
res1 = (y1-fitfunc1(x1, *p_best1))
sum_res1 = sum(res1)
σ_post1 = ma.sqrt(sum_res1/(y1.size))

# 输出拟合结果
print("---------------------------")
print("Best fit values:")
print("---------------------------")
print("A = (%.5f +/- %.5f)   百分比误差 = %.5f" % (p_best1[0],sqrt(cov1[0,0]),sqrt(cov1[0,0])*100/p_best1[0]))
print("R = (%.5f +/- %.5f) Ω 百分比误差 = %.5f" % (p_best1[1],sqrt(cov1[1,1]),sqrt(cov1[1,1])*100/p_best1[1]))
print("L = (%.5f +/- %.5f) μH 百分比误差 = %.5f" % (p_best1[2]*1E+6,sqrt(cov1[2,2])*1E+6,sqrt(cov1[2,2])*100/p_best1[2]))
print("C = (%.5f +/- %.5f) pF 百分比误差 = %.5f" % (p_best1[3]*1E+12,sqrt(cov1[3,3])*1E+12,sqrt(cov1[3,3])*100/p_best1[3]))
print("---------------------------")

# 绘制拟合图与残差图
fig1 = plt.figure(1, figsize=(9,7))
frame1a=fig1.add_axes((.1,.3,.7,.5))

plt.errorbar(x1, y1, yerr=σ_y1, fmt='.', label='实验数据', capsize = 4)
_pts = np.linspace(x1[0], x1[-1], 1000)
plt.plot(_pts, fitfunc1(_pts, *p_best1), label='拟合曲线')
plt.title("R两端的放大倍数")
plt.xlabel("频率 [kHz]")
plt.ylabel(r"A = $V_{out}/V_{in}$")
plt.legend()
plt.tick_params(bottom = False)
plt.grid()
frame1a.set_xticklabels([])

# 残差图
frame1b=fig1.add_axes((.1,.1,.7,.19))
plt.errorbar(x1, res1, yerr = σ_y1, fmt ='.', capsize = 4)
plt.xlabel("频率 [kHz]")
plt.ylabel(r"$A_{测量}-A_{拟合}$")
plt.grid()

# plt.savefig("fit_result.png", dpi = 200, bbox_inches = "tight")

我已经尝试过这些方法,但都没有解决问题:

  • 去掉参数的bounds=(0, +np.inf)限制,但这样得到的参数误差大到离谱,完全不合理;
  • 给参数重命名,避免和初始值变量名冲突,但没有改善;
  • 调整初始参数值(虽然理论上这些初始值是实测的,应该没问题),拟合效果还是很差;
  • 尝试用lmfit库进行拟合,结果同样不理想。

我实在搞不懂问题出在哪,明明只有A是未知参数,拟合却完全不对。有没有大佬能帮我看看函数实现、拟合设置或者数据处理哪里有问题?万分感谢!

备注:内容来源于stack exchange,提问作者Gabriele

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 11:54:31