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

Scipy optimize curve_fit异常:拟合结果异常且报协方差无法估计警告

Scipy曲线拟合异常问题排查

问题重现

运行提供的代码后出现两个异常:

  • 拟合曲线仅为第一条数据点附近的微小水平线
  • 抛出OptimizeWarning: Covariance of the parameters could not be estimated警告

原代码(补全缺失的numpy导入):

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

x_data = np.linspace(0,11,12)
y_data = np.array([0.02471114, 0.02057292, 0.01752668, 0.01494543, 0.01273249, 0.0110999 , 0.00946524, 0.00805622, 0.00670716, 0.00558925, 0.00465331, 0.00387775])

def func(x,a,b):
    return ((a-1)*(-b*x - (0.024711**(1-a)/(1-a))))**(1/(1-a))
popt,pcov = optimize.curve_fit(func, x_data, y_data, p0=[1.1,0.1])

a_opt, b_opt = popt
x_model = np.linspace(min(x_data), max(y_data), 100)
y_model = func(x_model, a_opt, b_opt) 
plt.scatter(x_data, y_data)
plt.plot(x_model, y_model, color='r')
plt.show()

问题根源分析

1. x_model的范围完全错误

代码中x_model = np.linspace(min(x_data), max(y_data), 100)错误地将x的范围设为[0, 0.0247],而原始x_data的范围是[0,11],导致拟合曲线仅在x趋近于0的极小区间绘制,视觉上呈现为水平线。

2. 拟合函数存在数值不稳定性

原函数形式过于复杂,且硬编码了第一个y值0.024711,当参数a接近1时,1-a为极小值,会引发:

  • 幂运算0.024711**(1-a)的精度丢失或数值溢出
  • 分母为极小值导致的计算爆炸,使得拟合算法无法找到有效参数优化方向

3. 初始参数加剧数值问题

初始参数p0=[1.1,0.1]中a非常接近1,进一步放大了数值稳定性问题,导致curve_fit无法收敛,无法估计参数协方差,最终抛出警告。

修复方案

步骤1:修正x_model的范围

将x_model的范围改为与原始x_data一致:

x_model = np.linspace(min(x_data), max(x_data), 100)

步骤2:更换更适配数据的拟合模型

原函数形式复杂且依赖硬编码值,建议使用更贴合数据单调递减趋势的指数衰减模型:

def func(x, c, b):
    return c * np.exp(-b * x)

步骤3:设置合理初始参数

针对新模型设置符合数据特征的初始参数,避免数值不稳定:

popt, pcov = optimize.curve_fit(func, x_data, y_data, p0=[0.025, 0.1])

完整修复代码

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

x_data = np.linspace(0,11,12)
y_data = np.array([0.02471114, 0.02057292, 0.01752668, 0.01494543, 0.01273249, 0.0110999 , 0.00946524, 0.00805622, 0.00670716, 0.00558925, 0.00465331, 0.00387775])

# 使用指数衰减模型,适配数据递减趋势
def func(x, c, b):
    return c * np.exp(-b * x)

# 设定合理初始参数
popt, pcov = optimize.curve_fit(func, x_data, y_data, p0=[0.025, 0.1])

c_opt, b_opt = popt
x_model = np.linspace(min(x_data), max(x_data), 100)
y_model = func(x_model, c_opt, b_opt) 

plt.scatter(x_data, y_data, label='原始数据')
plt.plot(x_model, y_model, color='r', label=f'拟合曲线: y={c_opt:.4f}*exp(-{b_opt:.4f}x)')
plt.legend()
plt.show()

运行这段代码后,拟合曲线会完美贴合数据,且不会出现协方差估计警告。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 20:05:07