如何使用 scipy.optimize.least_squares 获得稳健的非线性回归拟合?
How to get a robust nonlinear regression fit using scipy.optimize.least_squares?
我的具体问题是我似乎无法将数据转换为浮点数。我有数据,只是想使用我的模型方程拟合稳健曲线:
y = a * e^(-b*z)
这本食谱是我的参考:click
以下是我的尝试。我得到这个:
TypeError: 'data type not understood'
我认为这是因为我的列是字符串,所以我尝试了 pd.Series.astype()
。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import least_squares
for i in range(1):
def model(z, a, b):
y = a * np.exp(-b * z)
return y
data = pd.read_excel('{}.xlsx'.format(600+i), names = ['EdGnd','380','395','412','443','465','490','510','520','532','555','560','565','589','625','665','670','683','694','710','Temp','z','EdZTemp','Tilt','Roll','EdZVin'])
data.dropna(axis = 0, how = 'any')
data.astype('float')
np.dtype(data)
data.plot.scatter('z','380')
def fun(x, z, y):
return x[0] * np.exp(-x[1] * z) - y
x0 = np.ones(3)
rbst1 = least_squares(fun, x0, loss='soft_l1', f_scale=0.1, args=('z', 'ed380'))
y_robust = model('z', *rbst1.x)
plt.plot('z', y_robust, label='robust lsq')
plt.xlabel('$z$')
plt.ylabel('$Ed$')
plt.legend();
我认为问题在于您在 args
中传递了 'z'
,这是一个字符串,因此不能用于乘法。
下面是一些使用 curve_fit 的代码,它使用 least_squares
但可能更容易使用:
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
# your model definition
def model(z, a, b):
return a * np.exp(-b * z)
# your input data
x = np.array([20, 30, 40, 50, 60])
y = np.array([5.4, 4.0, 3.0, 2.2, 1.6])
# do the fit with some initial values
popt, pcov = curve_fit(model, x, y, p0=(5, 0.1))
# prepare some data for a plot
xx = np.linspace(20, 60, 1000)
yy = model(xx, *popt)
plt.plot(x, y, 'o', xx, yy)
plt.title('Exponential Fit')
plt.show()
这将绘制
您可以尝试根据您的需要调整此代码。
如果你想使用f_scale
你可以使用:
popt, pcov = curve_fit(model, x, y, p0=(5, 0.1), method='trf', f_scale=0.1)
参见 documentation:
kwargs
Keyword arguments passed to leastsq for method='lm' or least_squares otherwise.
如果你有一个未绑定的问题,默认情况下使用 method='lm'
,它使用不接受 f_scale
作为关键字的 leastsq
。因此,我们可以使用 method='trf'
,然后使用 least_squares
,接受 f_scale
。
我的具体问题是我似乎无法将数据转换为浮点数。我有数据,只是想使用我的模型方程拟合稳健曲线:
y = a * e^(-b*z)
这本食谱是我的参考:click
以下是我的尝试。我得到这个:
TypeError: 'data type not understood'
我认为这是因为我的列是字符串,所以我尝试了 pd.Series.astype()
。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import least_squares
for i in range(1):
def model(z, a, b):
y = a * np.exp(-b * z)
return y
data = pd.read_excel('{}.xlsx'.format(600+i), names = ['EdGnd','380','395','412','443','465','490','510','520','532','555','560','565','589','625','665','670','683','694','710','Temp','z','EdZTemp','Tilt','Roll','EdZVin'])
data.dropna(axis = 0, how = 'any')
data.astype('float')
np.dtype(data)
data.plot.scatter('z','380')
def fun(x, z, y):
return x[0] * np.exp(-x[1] * z) - y
x0 = np.ones(3)
rbst1 = least_squares(fun, x0, loss='soft_l1', f_scale=0.1, args=('z', 'ed380'))
y_robust = model('z', *rbst1.x)
plt.plot('z', y_robust, label='robust lsq')
plt.xlabel('$z$')
plt.ylabel('$Ed$')
plt.legend();
我认为问题在于您在 args
中传递了 'z'
,这是一个字符串,因此不能用于乘法。
下面是一些使用 curve_fit 的代码,它使用 least_squares
但可能更容易使用:
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
# your model definition
def model(z, a, b):
return a * np.exp(-b * z)
# your input data
x = np.array([20, 30, 40, 50, 60])
y = np.array([5.4, 4.0, 3.0, 2.2, 1.6])
# do the fit with some initial values
popt, pcov = curve_fit(model, x, y, p0=(5, 0.1))
# prepare some data for a plot
xx = np.linspace(20, 60, 1000)
yy = model(xx, *popt)
plt.plot(x, y, 'o', xx, yy)
plt.title('Exponential Fit')
plt.show()
这将绘制
您可以尝试根据您的需要调整此代码。
如果你想使用f_scale
你可以使用:
popt, pcov = curve_fit(model, x, y, p0=(5, 0.1), method='trf', f_scale=0.1)
参见 documentation:
kwargs
Keyword arguments passed to leastsq for method='lm' or least_squares otherwise.
如果你有一个未绑定的问题,默认情况下使用 method='lm'
,它使用不接受 f_scale
作为关键字的 leastsq
。因此,我们可以使用 method='trf'
,然后使用 least_squares
,接受 f_scale
。