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

使用curve_fit进行非线性回归拟合结果与数据不符求助

问题分析与解决办法

首先得说,你遇到的curve_fit拟合结果和数据完全不符的问题,大概率是由以下两个核心原因导致的:

1. 缺少合理的初始参数猜测

curve_fit默认会把初始参数设为[1, 1, 1],但你的拟合函数是a/(x²) + b + c x²——这种同时包含x的倒数项和高次项的函数,对初始参数的敏感度极高。如果你的数据对应的真实参数和默认值偏差较大,拟合算法很容易收敛到局部最优解,甚至完全偏离预期的结果。

举个例子:

  • 当omega很小时,函数值主要由a/(x²)主导,如果数据在小omega区间的Z值很大,那a应该是一个较大的数,但默认初始值为1,会直接让算法找错优化方向;
  • 当omega很大时,函数值由c x²主导,如果Z随omega增大快速上升/下降,c的初始值也需要对应调整才能让算法收敛到正确解。

2. 数据尺度差异过大引发数值不稳定

你的函数里同时存在1/x²和x²项,如果omega的数值范围跨度很大(比如从1e-3到1e3),这两个项的数值量级会差好几个数量级,拟合时优化器很难平衡不同项的权重,最终导致参数估计出错。


具体解决办法

方法一:添加合理的初始参数猜测

先根据你的数据趋势大致估算a、b、c的初始值,然后传给curve_fit的p0参数,引导算法找到正确的收敛方向:

# 估算初始参数(请根据你的实际数据调整阈值)
# 取omega较小的部分,计算a的初始值:a ≈ Z * x²
small_omega_mask = omega < 0.1
a_init = np.mean(Z[small_omega_mask] * omega[small_omega_mask]**2)

# 取omega较大的部分,计算c的初始值:c ≈ Z / x²
large_omega_mask = omega > 10
c_init = np.mean(Z[large_omega_mask] / omega[large_omega_mask]**2)

# 取中间omega的部分,计算b的初始值:b ≈ Z - a/(x²) - c x²
mid_omega_mask = (omega >= 0.1) & (omega <=10)
b_init = np.mean(Z[mid_omega_mask] - a_init/(omega[mid_omega_mask]**2) - c_init*(omega[mid_omega_mask]**2))

# 传入初始参数进行拟合
popt, poc = curve_fit(func, omega, Z, p0=[a_init, b_init, c_init])

方法二:对数据进行归一化处理

把omega和Z都缩放到相近的量级(比如0-1区间),消除数值尺度差异带来的干扰,拟合完成后再把参数转换回原尺度:

# 归一化omega和Z
omega_scaled = omega / np.max(omega)
Z_scaled = Z / np.max(Z)

# 定义适配归一化数据的拟合函数
def func_scaled(x, a_scaled, b_scaled, c_scaled):
    omega_max = np.max(omega)
    Z_max = np.max(Z)
    # 转换回原函数逻辑
    return (a_scaled * Z_max * omega_max**2) / (x**2 * omega_max**2) + b_scaled * Z_max + (c_scaled * Z_max / omega_max**2) * (x**2 * omega_max**2)

# 拟合归一化后的数据
popt_scaled, poc_scaled = curve_fit(func_scaled, omega_scaled, Z_scaled)

# 将拟合参数转换回原尺度
a = popt_scaled[0] * np.max(Z) * np.max(omega)**2
b = popt_scaled[1] * np.max(Z)
c = popt_scaled[2] * np.max(Z) / np.max(omega)**2
popt = [a, b, c]

方法三:过滤异常值

如果你的omega中存在接近0的值,a/(x²)会变得极大,严重干扰拟合结果。可以先过滤掉这些异常点:

# 过滤掉omega接近0的点(阈值可根据数据调整)
valid_mask = omega > 1e-5
omega_valid = omega[valid_mask]
Z_valid = Z[valid_mask]

# 用过滤后的数据进行拟合
popt, poc = curve_fit(func, omega_valid, Z_valid, p0=[a_init, b_init, c_init])

# 绘图时同步使用过滤后的数据
plt.plot(omega_valid, Z_valid, 'bo', markersize=3.5)
plt.plot(omega_valid, func(omega_valid, *popt))

最后,你可以打印拟合后的参数popt和协方差矩阵poc:如果协方差矩阵的对角线元素很大,说明参数的不确定性很高,这时候需要再调整初始参数或者数据处理方式。

内容的提问来源于stack exchange,提问作者Xabier Garcia Andrade

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:08:21