如何在使用 lmfit 进行最小化时修复 'The array returned by a function changed size between calls'?
How to fix 'The array returned by a function changed size between calls' while using lmfit for minimization?
如何在使用 lmfit
进行最小化时修复错误 'The array returned by a function changed size between calls' 的代码?
请在下面找到我的代码:
import numpy as np
import pandas as pd
import lmfit as lf
#model needs to be fitted
x0 = 75
def func(params, x, Tsky):
A = params['amp']
w = params['width']
t = params['thickness']
v0 = params['mid_freq']
b0 = params['b0']
b1 = params['b1']
b2 = params['b2']
b3 = params['b3']
b4 = params['b4']
B = (4 * (x - v0)**2. / w**2.) * np.log(-1./t * np.log((1 + np.exp(-t))/2))
T21 = -A * (1 - np.exp(-t * np.exp(B)))/(1 - np.exp(-t))
model = T21 + b0 * ((x/x0)**(-2.5 + b1 + b2 * np.log(x/x0))) * np.exp(-b3*(x/x0)**-2.) + b4 * (x/x0)**-2.
return (Tsky-model)
#read the data
df = pd.read_csv('figure1_plotdata.csv')
data_list = df.T.values.tolist()
xdata = np.array(data_list[0])
Tsky = np.array(data_list[2])
#initial value of the parameters
params = lf.Parameters()
params.add('amp', value=0.2)
params.add('width', value=10)
params.add('thickness', value=5)
params.add('mid_freq', value=70)
params.add('b0', value=500)
params.add('b1', value=-0.5)
params.add('b2', value=-0.5)
params.add('b3', value=-0.5)
params.add('b4', value=500)
#minimize the function
out = lf.minimize(func, params, args=(xdata, Tsky), method='leastsq', kws=None, iter_cb=None, scale_covar=True, nan_policy='omit', calc_covar=True)
print(lf.fit_report(out))
错误信息如下:
File "/home/ankita/Dropbox/Python/Bowman_work/min.py", line 81, in <module>
out = lf.minimize(func, params, args=(xdata, Tsky), method='leastsq', kws=None, iter_cb=None, scale_covar=True, nan_policy='omit', calc_covar=True)
File "/home/ankita/anaconda3/lib/python3.7/site-packages/lmfit-0.9.13-py3.7.egg/lmfit/minimizer.py", line 2300, in minimize
return fitter.minimize(method=method)
File "/home/ankita/anaconda3/lib/python3.7/site-packages/lmfit-0.9.13-py3.7.egg/lmfit/minimizer.py", line 1949, in minimize
return function(**kwargs)
File "/home/ankita/anaconda3/lib/python3.7/site-packages/lmfit-0.9.13-py3.7.egg/lmfit/minimizer.py", line 1492, in leastsq
lsout = scipy_leastsq(self.__residual, variables, **lskws)
File "/home/ankita/anaconda3/lib/python3.7/site-packages/scipy/optimize/minpack.py", line 394, in leastsq
gtol, maxfev, epsfcn, factor, diag)
**ValueError: The array returned by a function changed size between calls**
如果你用过
out = lf.minimize(func, params,...,nan_policy='raise')
您会看到出现异常,告诉您存在 NaN。当您使用 nan_policy='omit'
时,您的模型生成的任何此类 NaN 都会从残差数组中移除,因此数组的大小会在两次调用之间发生变化。拟合不能处理 NaN 或数组大小的变化——你必须消除它们。
特别是 np.log(x)
在 x<0
时是 NaN。您的 np.log()
有一个复杂的参数,该参数取决于参数 t
的值。如果对于 t
的某个值,该参数低于 0,则该模型具有 NaN 并且没有意义。
您必须确保此参数不能低于 0。可能是
使用
params.add('thickness', value=5, min=0)
足够了。但是您应该更详细地检查您的模型并确定它是否有意义。
我觉得你的模型很复杂。我猜不出这样的模型是从哪里来的。采用多个 np.exp()
和 np.log()
有点要求数值不稳定性。所以,我不知道简单地强制 t
为正是否会很合适,但它可能会为您指明正确的方向。
如何在使用 lmfit
进行最小化时修复错误 'The array returned by a function changed size between calls' 的代码?
请在下面找到我的代码:
import numpy as np
import pandas as pd
import lmfit as lf
#model needs to be fitted
x0 = 75
def func(params, x, Tsky):
A = params['amp']
w = params['width']
t = params['thickness']
v0 = params['mid_freq']
b0 = params['b0']
b1 = params['b1']
b2 = params['b2']
b3 = params['b3']
b4 = params['b4']
B = (4 * (x - v0)**2. / w**2.) * np.log(-1./t * np.log((1 + np.exp(-t))/2))
T21 = -A * (1 - np.exp(-t * np.exp(B)))/(1 - np.exp(-t))
model = T21 + b0 * ((x/x0)**(-2.5 + b1 + b2 * np.log(x/x0))) * np.exp(-b3*(x/x0)**-2.) + b4 * (x/x0)**-2.
return (Tsky-model)
#read the data
df = pd.read_csv('figure1_plotdata.csv')
data_list = df.T.values.tolist()
xdata = np.array(data_list[0])
Tsky = np.array(data_list[2])
#initial value of the parameters
params = lf.Parameters()
params.add('amp', value=0.2)
params.add('width', value=10)
params.add('thickness', value=5)
params.add('mid_freq', value=70)
params.add('b0', value=500)
params.add('b1', value=-0.5)
params.add('b2', value=-0.5)
params.add('b3', value=-0.5)
params.add('b4', value=500)
#minimize the function
out = lf.minimize(func, params, args=(xdata, Tsky), method='leastsq', kws=None, iter_cb=None, scale_covar=True, nan_policy='omit', calc_covar=True)
print(lf.fit_report(out))
错误信息如下:
File "/home/ankita/Dropbox/Python/Bowman_work/min.py", line 81, in <module>
out = lf.minimize(func, params, args=(xdata, Tsky), method='leastsq', kws=None, iter_cb=None, scale_covar=True, nan_policy='omit', calc_covar=True)
File "/home/ankita/anaconda3/lib/python3.7/site-packages/lmfit-0.9.13-py3.7.egg/lmfit/minimizer.py", line 2300, in minimize
return fitter.minimize(method=method)
File "/home/ankita/anaconda3/lib/python3.7/site-packages/lmfit-0.9.13-py3.7.egg/lmfit/minimizer.py", line 1949, in minimize
return function(**kwargs)
File "/home/ankita/anaconda3/lib/python3.7/site-packages/lmfit-0.9.13-py3.7.egg/lmfit/minimizer.py", line 1492, in leastsq
lsout = scipy_leastsq(self.__residual, variables, **lskws)
File "/home/ankita/anaconda3/lib/python3.7/site-packages/scipy/optimize/minpack.py", line 394, in leastsq
gtol, maxfev, epsfcn, factor, diag)
**ValueError: The array returned by a function changed size between calls**
如果你用过
out = lf.minimize(func, params,...,nan_policy='raise')
您会看到出现异常,告诉您存在 NaN。当您使用 nan_policy='omit'
时,您的模型生成的任何此类 NaN 都会从残差数组中移除,因此数组的大小会在两次调用之间发生变化。拟合不能处理 NaN 或数组大小的变化——你必须消除它们。
特别是 np.log(x)
在 x<0
时是 NaN。您的 np.log()
有一个复杂的参数,该参数取决于参数 t
的值。如果对于 t
的某个值,该参数低于 0,则该模型具有 NaN 并且没有意义。
您必须确保此参数不能低于 0。可能是
使用
params.add('thickness', value=5, min=0)
足够了。但是您应该更详细地检查您的模型并确定它是否有意义。
我觉得你的模型很复杂。我猜不出这样的模型是从哪里来的。采用多个 np.exp()
和 np.log()
有点要求数值不稳定性。所以,我不知道简单地强制 t
为正是否会很合适,但它可能会为您指明正确的方向。