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

七参数四指数函数数据拟合报错求助:生成NaN值终止拟合

解决四指数函数拟合时的NaN报错问题

问题背景

需要将以下时间-浓度数据拟合到七参数四指数函数:

# 时间数据(单位:min/10)
time = np.array([0.075, 0.1, 0.125, 0.15, 0.175, 0.2, 0.25, 0.3, 0.35, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 4.5, 6])
# 浓度数据
concentration = np.array([2.148738, 24.88158, 61.81409, 82.55928, 79.09638, 79.45628, 28.19074, 18.6571, 16.04993, 14.16715, 11.87659, 9.680828, 7.948303, 8.233573, 7.285041, 6.576602, 6.100967, 5.581709, 5.389457])

目标拟合函数:
$$Cp(t) = A_1 e^{-L_1 t} + A_2 e^{-L_2 t} + A_3 e^{-L_3 t} - (A_1+A_2+A_3)e^{-L_4 t}$$

使用curve_fit时出现报错:

ValueError: The model function generated NaN values and the fit aborted! Please check your model function and/or set boundaries on parameters where applicable. In cases like this, using "nan_policy='omit'" will probably not work.

报错原因分析

  1. 循环实现的潜在问题:原函数用循环逐个计算值,容易出现单个元素的数值溢出,且效率低下;
  2. 初始参数不合理:七参数拟合对初始值敏感度高,默认初始值会导致迭代过程中参数进入不合理范围,引发NaN;
  3. 参数约束不足:仅设置参数下限,未对L值设置上限,过大的L会导致指数计算溢出。

解决步骤与完整代码

1. 重写拟合函数(向量运算替代循环)

用numpy向量运算直接处理整个数组,避免循环中的单个元素错误,提升稳定性与效率:

def Cp(x, A1, L1, A2, L2, A3, L3, L4):
    term1 = A1 * np.exp(-x * L1)
    term2 = A2 * np.exp(-x * L2)
    term3 = A3 * np.exp(-x * L3)
    term4 = (A1 + A2 + A3) * np.exp(-x * L4)
    return term1 + term2 + term3 - term4

2. 优化参数初始值与约束

根据数据趋势(快速上升后快速下降,再缓慢衰减)手动设置初始值,并给L参数添加上限,防止指数溢出:

import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import numpy as np
import lmfit

# 重写后的拟合函数
def Cp(x, A1, L1, A2, L2, A3, L3, L4):
    term1 = A1 * np.exp(-x * L1)
    term2 = A2 * np.exp(-x * L2)
    term3 = A3 * np.exp(-x * L3)
    term4 = (A1 + A2 + A3) * np.exp(-x * L4)
    return term1 + term2 + term3 - term4

# 加载数据
time = np.array([0.075, 0.1, 0.125, 0.15, 0.175, 0.2, 0.25, 0.3, 0.35, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 4.5, 6])
concentration = np.array([2.148738, 24.88158, 61.81409, 82.55928, 79.09638, 79.45628, 28.19074, 18.6571, 16.04993, 14.16715, 11.87659, 9.680828, 7.948303, 8.233573, 7.285041, 6.576602, 6.100967, 5.581709, 5.389457])

# 创建模型与参数设置
model = lmfit.Model(Cp, independent_vars=['x'])
params = model.make_params(
    A1=80, L1=20,
    A2=50, L2=10,
    A3=20, L3=5,
    L4=0.5
)

# 添加参数约束:所有参数非负,L值上限防止溢出
for param_name in params:
    params[param_name].min = 0
    if param_name.startswith('L'):
        params[param_name].max = 100

# 执行拟合
fit_result = model.fit(concentration, x=time, params=params)

# 输出拟合报告
print(fit_result.fit_report())

# 绘制拟合结果
plt.scatter(time, concentration, label='实验数据')
plt.plot(time, fit_result.best_fit, 'r-', label='拟合曲线')
plt.xlabel('时间 (min/10)')
plt.ylabel('浓度')
plt.legend()
plt.show()

关键改进说明

  • 向量运算:消除循环带来的数值不稳定问题,同时提升计算速度;
  • 合理初始值:根据数据趋势设定初始值,帮助拟合算法快速收敛到合理参数范围;
  • 参数约束:给L值设置上限,避免指数计算中出现溢出导致NaN;
  • lmfit直接拟合:相比curve_fit,lmfit的参数优化机制更适合多参数复杂模型,自带的参数约束与报告输出更便捷。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 13:50:47