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

使用lmfit拟合自定义对数模型时触发NaN值错误排查

自定义对数函数拟合触发NaN错误排查

数据

y=[2.103402,2.426855,1.011672,1.595371,1.861879,2.492542,2.567561,4.685010,4.452643,5.321630,6.637233,
6.109260,6.220958,5.928408,5.654726,5.498096,5.468448,6.128418,6.071376,6.487270,6.609533,6.907320,
7.626838,8.432065,9.749410,8.976752,8.742036,8.779956,8.212357,8.578200,9.170012,9.134267,9.199465,
9.094945,9.342948,9.802524,10.959913,10.488497,10.892593,10.673570,10.608582,10.036824,9.741473]

x=[300,400,500,600,700,800,900,1000,1100,1200,1300,1400,1500,1600,1700,1800,1900,2000,2100,2200,2300,
2400,2500,2600,2700,2800,2900,3000,3100,3200,3300,3400,3500,3600,3700,3800,3900,4000,4100,4200,4300,4400,4500]

数据形态:整体呈现先上升后趋于平稳的趋势。

自定义拟合函数

def log_n_func(x, a, b, c, n):
    return a*(np.log(b+x)/np.log(n))+c

尝试的两种实现方式

方式一

import lmfit

def log_n_func(x, a, b, c, n):
    return a*(np.log(b+x)/np.log(n))+c

regressor = lmfit.Model(log_n_func)                  
initial_guess = dict(a=3.61, b=443.86, c=-34, n=2)                
results = regressor.fit(data=y, x=x, **initial_guess)
y_fit = results.best_fit

方式二

from lmfit import Model, Parameters

model = Model(log_n_func, independent_vars=['x'], param_names=["a", "b", "c", "n"])  
params = Parameters()
params.add("a", value=3.6)
params.add("b", value=440)
params.add("c", value=-34)
params.add("n", value=2)
result = model.fit(data=y, params=params, x=x)

触发的错误

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.

问题

请问我哪里操作出错了?


解决方案

NaN错误的根源是拟合过程中参数被优化到了非法取值范围,导致对数函数或除法运算失效:

  1. 参数n的问题:当n被调整到≤1时,np.log(n)会变成0(n=1时)或负数(n<1时),除以0直接产生NaN;结合数据趋势,n作为对数底数应该大于1,因此需要限制n的最小值。
  2. 参数b的问题:x的最小值是300,如果b被调整到≤-300,会导致b+x≤0,而np.log的输入不能是非正数,直接产生NaN,因此需要限制b的最小值。

修改后的代码示例

方式一优化版

import lmfit
import numpy as np

def log_n_func(x, a, b, c, n):
    return a*(np.log(b+x)/np.log(n))+c

regressor = lmfit.Model(log_n_func)                  
# 生成参数对象并设置边界
params = regressor.make_params(a=3.61, b=443.86, c=-34, n=2)
params['n'].min = 1.0001  # 确保n>1,避免log(n)为0或负数
params['b'].min = -299    # 确保b+x>0(x最小为300)
results = regressor.fit(data=y, x=x, params=params)
y_fit = results.best_fit
# 查看拟合结果报告
print(results.fit_report())

方式二优化版

from lmfit import Model, Parameters
import numpy as np

def log_n_func(x, a, b, c, n):
    return a*(np.log(b+x)/np.log(n))+c

model = Model(log_n_func, independent_vars=['x'], param_names=["a", "b", "c", "n"])  
params = Parameters()
params.add("a", value=3.6)
params.add("b", value=440, min=-299)  # 限制b的最小值
params.add("c", value=-34)
params.add("n", value=2, min=1.0001)   # 限制n的最小值
result = model.fit(data=y, params=params, x=x)
# 查看拟合结果报告
print(result.fit_report())

通过给参数设置合理的取值边界,就能避免拟合过程中产生NaN,顺利完成拟合。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 20:45:59