RuntimeWarning:无效值非线性适合多个参数和自变量
RuntimeWarning: invalid value non-linear-fit with multiple parameters and independent variable
几周前我刚刚学过 python,目前我在将数据拟合到给定函数时遇到问题。我尝试了不同的方法来拟合我的数据,但我不断收到错误 RuntimeWarning: invalid value, or sth similiar (like divided by zero)。
我在下面的 python 函数中定义了我想要适应的函数:
def pval(x, A_0, n_0, E_0, a_troe, T_3, T_1, T_2,):#depending on the method 'p' insted of the parameters i.e: pval(x,p)
#A_0, n_0, E_0, a_troe, T_3, T_1, T_2 = p[0:7]
A_u = 14099393133.869781
n_u = 0.043936990336299386
E_u = 16281.619590689397
k_u = A_u * (x[:,0]**n_u) * numpy.exp(-E_u/x[:,0])
x_troe = ((A_0 * (x[:,0]**n_0) * numpy.exp(-E_0 / x[:, 0])) / k_u) * (x[:, 1] * 1.01325 * 10**(-1)) / (8.3141 * x[:, 0])
Fc = (1-a_troe) * numpy.exp(-x[:,0]/T_3) + a_troe * numpy.exp(-x[:,0]/T_1) + numpy.exp(-T_2/x[:,0])
O = numpy.log10(x_troe) - 0.4 - 0.67 * numpy.log10(Fc)
U = 0.75 - 1.27 * numpy.log10(Fc) - 0.14 * (numpy.log10(x_troe) - 0.4 - 0.67 * numpy.log10(Fc))
log_F = numpy.log10(Fc)/(1 + (O/U)**2)
f = numpy.log10(k_u) - numpy.log10(1+1/x_troe) + log_F
return f
如你所见,我想要拟合 7 个参数,函数有 2 个自变量。
这里给出了我的数据的摘录,其中 none 我尝试过的方法有效:
x= [[1.0e+03 1.0e-02]
[1.0e+03 1.0e-01]
[1.0e+03 1.0e+00]
[1.0e+03 1.0e+01]
[1.0e+03 1.0e+02]
[1.1e+03 1.0e-02]
[1.1e+03 1.0e-01]
[1.1e+03 1.0e+00]
[1.1e+03 1.0e+01]
[1.1e+03 1.0e+02]
[1.2e+03 1.0e-01]
[1.2e+03 1.0e+00]
[1.2e+03 1.0e+01]
[1.2e+03 1.0e+02]
[1.3e+03 1.0e+00]
[1.3e+03 1.0e+01]
[1.3e+03 1.0e+02]
[1.4e+03 1.0e+00]
[1.4e+03 1.0e+01]
[1.4e+03 1.0e+02]
[1.5e+03 1.0e+01]
[1.5e+03 1.0e+02]
[1.6e+03 1.0e+01]
[1.6e+03 1.0e+02]
[1.7e+03 1.0e+02]
[1.8e+03 1.0e+02]
[1.9e+03 1.0e+02]
[2.0e+03 1.0e+02]]
y = [2.89894501 2.99443594 3.11048533 3.18421145 3.20302744 3.15204054
3.37720969 3.62462651 3.78744276 3.83868541 3.64709041 4.00417085
4.26080811 4.36152197 4.28960902 4.63156552 4.79327409 4.50830342
4.9238101 5.15010835 5.1568065 5.44522578 5.34414656 5.68986891
5.89350044 6.06378356 6.20646696 6.32558954]
我尝试的第一个解决方案是 leastsq() 函数:
import numpy
from scipy import *
from scipy.optimize import leastsq
def residuals(p, y, x): # in this case pval defined as pval(x,p)
err = y - pval(x, p)
return err
startpars = numpy.array([1.88e+13, -1.03, 11980, 0.76, 1.0e+10, 1.74, 9.33e+09], dtype=numpy.float64)
plsq = leastsq(residuals, startpars, args=(y, x), maxfev=2000)
print(plsq)
输出:
RuntimeWarning: invalid value encountered in log10
我尝试了几个启动参数
下一个方法:curve_fit
import numpy
from scipy import *
from scipy.optimize import curve_fit
print(curve_fit(pval, x, y,))
其中 returns 与上一种方法相同的错误消息。我试图定义 startparameter 并设置边界,但这没有用
下一个 method:lmfit
import numpy
from lmfit import Model
startpars = numpy.array([1.88e+13, -1.03, 11980, 0.76, 1.0e+10, 1.74, 9.33e+09], dtype=numpy.float64)
lmfit_model = Model(pval)
lmfit_result = lmfit_model.fit(y, x=x, A_0 = startpars[0], n_0= startpars[1], E_0= startpars[2], a_troe= startpars[3], T_3= startpars[4], T_1= startpars[5], T_2= startpars[6])
lmfit_Rsquared = 1 - lmfit_result.residual.var() / numpy.var(y)
print('Fit R-squared:', lmfit_Rsquared, '\n')
print(lmfit_result.fit_report())
输出:
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.
我也尝试了网上找到的另一种解决方案。那里使用了 Levenberg–Marquardt 算法,但它的代码很长,我认为我的问题已经足够长了。但如果需要,我也可以 post 这个解决方案。
我在优化 运行 时打印了一些值,有些值确实变成了 inf 或 -inf,但是在设置边界之前写的没有用。
我希望你们中的任何人都有想法。预先感谢。
我希望我的问题表述清楚,以防您需要更多信息,我很乐意提供
这些消息告诉您,您的模型函数正在生成 NaN(不是数字),这使得拟合无法求解。对于您的模型函数,这几乎肯定来自 np.log()
或 np.exp()
.
np.log(x)
是 x<=0
的 NaN。
几乎所有使用np.log()
(或np.log10()
)的地方,您都应该检查或确保参数不能为负。由于拟合变量基本上可以具有任何值的组合(好吧,您可以添加界限,例如,如果某些变量永远不应该为负数),您可能需要使用模型函数来检查这一点。
稍微差一点,但需要注意的是,如果参数 >~700,np.exp()
可能会溢出到 np.Inf。有 Infs 也会导致适合停止,但更容易防范。
最后的评论:当值的尺度相差许多(比如 10)个数量级时,数值方法往往不能很好地完成工作。 lmfit
和 scipy.optimize.leastsq
中使用的 Levenberg-Marquardt 方法会尝试为您处理此问题,但如果您的变量具有已知比例,则让变量接近相同顺序通常是个好主意幅度(比如 1.e-5 到 1e5)并在模型函数中应用比例因子。
几周前我刚刚学过 python,目前我在将数据拟合到给定函数时遇到问题。我尝试了不同的方法来拟合我的数据,但我不断收到错误 RuntimeWarning: invalid value, or sth similiar (like divided by zero)。 我在下面的 python 函数中定义了我想要适应的函数:
def pval(x, A_0, n_0, E_0, a_troe, T_3, T_1, T_2,):#depending on the method 'p' insted of the parameters i.e: pval(x,p)
#A_0, n_0, E_0, a_troe, T_3, T_1, T_2 = p[0:7]
A_u = 14099393133.869781
n_u = 0.043936990336299386
E_u = 16281.619590689397
k_u = A_u * (x[:,0]**n_u) * numpy.exp(-E_u/x[:,0])
x_troe = ((A_0 * (x[:,0]**n_0) * numpy.exp(-E_0 / x[:, 0])) / k_u) * (x[:, 1] * 1.01325 * 10**(-1)) / (8.3141 * x[:, 0])
Fc = (1-a_troe) * numpy.exp(-x[:,0]/T_3) + a_troe * numpy.exp(-x[:,0]/T_1) + numpy.exp(-T_2/x[:,0])
O = numpy.log10(x_troe) - 0.4 - 0.67 * numpy.log10(Fc)
U = 0.75 - 1.27 * numpy.log10(Fc) - 0.14 * (numpy.log10(x_troe) - 0.4 - 0.67 * numpy.log10(Fc))
log_F = numpy.log10(Fc)/(1 + (O/U)**2)
f = numpy.log10(k_u) - numpy.log10(1+1/x_troe) + log_F
return f
如你所见,我想要拟合 7 个参数,函数有 2 个自变量。 这里给出了我的数据的摘录,其中 none 我尝试过的方法有效:
x= [[1.0e+03 1.0e-02]
[1.0e+03 1.0e-01]
[1.0e+03 1.0e+00]
[1.0e+03 1.0e+01]
[1.0e+03 1.0e+02]
[1.1e+03 1.0e-02]
[1.1e+03 1.0e-01]
[1.1e+03 1.0e+00]
[1.1e+03 1.0e+01]
[1.1e+03 1.0e+02]
[1.2e+03 1.0e-01]
[1.2e+03 1.0e+00]
[1.2e+03 1.0e+01]
[1.2e+03 1.0e+02]
[1.3e+03 1.0e+00]
[1.3e+03 1.0e+01]
[1.3e+03 1.0e+02]
[1.4e+03 1.0e+00]
[1.4e+03 1.0e+01]
[1.4e+03 1.0e+02]
[1.5e+03 1.0e+01]
[1.5e+03 1.0e+02]
[1.6e+03 1.0e+01]
[1.6e+03 1.0e+02]
[1.7e+03 1.0e+02]
[1.8e+03 1.0e+02]
[1.9e+03 1.0e+02]
[2.0e+03 1.0e+02]]
y = [2.89894501 2.99443594 3.11048533 3.18421145 3.20302744 3.15204054
3.37720969 3.62462651 3.78744276 3.83868541 3.64709041 4.00417085
4.26080811 4.36152197 4.28960902 4.63156552 4.79327409 4.50830342
4.9238101 5.15010835 5.1568065 5.44522578 5.34414656 5.68986891
5.89350044 6.06378356 6.20646696 6.32558954]
我尝试的第一个解决方案是 leastsq() 函数:
import numpy
from scipy import *
from scipy.optimize import leastsq
def residuals(p, y, x): # in this case pval defined as pval(x,p)
err = y - pval(x, p)
return err
startpars = numpy.array([1.88e+13, -1.03, 11980, 0.76, 1.0e+10, 1.74, 9.33e+09], dtype=numpy.float64)
plsq = leastsq(residuals, startpars, args=(y, x), maxfev=2000)
print(plsq)
输出:
RuntimeWarning: invalid value encountered in log10
我尝试了几个启动参数 下一个方法:curve_fit
import numpy
from scipy import *
from scipy.optimize import curve_fit
print(curve_fit(pval, x, y,))
其中 returns 与上一种方法相同的错误消息。我试图定义 startparameter 并设置边界,但这没有用 下一个 method:lmfit
import numpy
from lmfit import Model
startpars = numpy.array([1.88e+13, -1.03, 11980, 0.76, 1.0e+10, 1.74, 9.33e+09], dtype=numpy.float64)
lmfit_model = Model(pval)
lmfit_result = lmfit_model.fit(y, x=x, A_0 = startpars[0], n_0= startpars[1], E_0= startpars[2], a_troe= startpars[3], T_3= startpars[4], T_1= startpars[5], T_2= startpars[6])
lmfit_Rsquared = 1 - lmfit_result.residual.var() / numpy.var(y)
print('Fit R-squared:', lmfit_Rsquared, '\n')
print(lmfit_result.fit_report())
输出:
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.
我也尝试了网上找到的另一种解决方案。那里使用了 Levenberg–Marquardt 算法,但它的代码很长,我认为我的问题已经足够长了。但如果需要,我也可以 post 这个解决方案。
我在优化 运行 时打印了一些值,有些值确实变成了 inf 或 -inf,但是在设置边界之前写的没有用。
我希望你们中的任何人都有想法。预先感谢。 我希望我的问题表述清楚,以防您需要更多信息,我很乐意提供
这些消息告诉您,您的模型函数正在生成 NaN(不是数字),这使得拟合无法求解。对于您的模型函数,这几乎肯定来自 np.log()
或 np.exp()
.
np.log(x)
是 x<=0
的 NaN。
几乎所有使用np.log()
(或np.log10()
)的地方,您都应该检查或确保参数不能为负。由于拟合变量基本上可以具有任何值的组合(好吧,您可以添加界限,例如,如果某些变量永远不应该为负数),您可能需要使用模型函数来检查这一点。
稍微差一点,但需要注意的是,如果参数 >~700,np.exp()
可能会溢出到 np.Inf。有 Infs 也会导致适合停止,但更容易防范。
最后的评论:当值的尺度相差许多(比如 10)个数量级时,数值方法往往不能很好地完成工作。 lmfit
和 scipy.optimize.leastsq
中使用的 Levenberg-Marquardt 方法会尝试为您处理此问题,但如果您的变量具有已知比例,则让变量接近相同顺序通常是个好主意幅度(比如 1.e-5 到 1e5)并在模型函数中应用比例因子。