【问题标题】:How to get a robust nonlinear regression fit using scipy.optimize.least_squares?如何使用 scipy.optimize.least_squares 获得稳健的非线性回归拟合?
【发布时间】:2018-10-22 13:18:17
【问题描述】:

我的具体问题是我似乎无法将我的数据转换为浮点数。我有数据,只是想用我的模型方程拟合一条稳健的曲线:

y = a * e^(-b*z)

这本食谱是我的参考:click

以下是我的尝试。我得到了这个:

TypeError: '数据类型不理解'

我认为这是因为我的列是字符串,所以我尝试了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', '380') 应该做什么? z 的值是否应该具有 380 的值?两者都是字符串,因此您不能将其用于乘法。你能提供一个用于调试目的的小数据集吗?!
  • 非常感谢您的回复! least_squares 中的参数是我想要适合的 x 和 y 值。不知道为什么,但看看食谱,作者似乎就是这么做的。 z是深度,380是光的波长。我将尝试将字符串放入数组中。
  • 我的数据长度在不同文件之间变化到大约 100-200 行。它有 26 列宽。很遗憾,我无法上传文件。
  • 嗯,我正在尝试使用 pd.Series.astype() 将我的数据作为浮点数。 np.dtype() 是说:数据类型不被理解。这是我第一次使用熊猫。

标签: python scipy least-squares non-linear-regression robust


【解决方案1】:

我认为问题在于您在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

关键字参数传递给至少method='lm'或least_squares。

如果您有未绑定的问题,默认情况下使用method='lm',它使用不接受f_scale 作为关键字的leastsq。因此,我们可以使用method='trf',然后使用least_squares,它接受f_scale

【讨论】:

  • 谢谢!这行得通,但是由于 f_scale 参数不允许异常值数据的影响,我打算与 minimum_squares 进行稳健拟合。有什么办法可以用curve_fit消除异常数据?
  • @JacobCooper:可以在curve_fit 中使用f_scale;我相应地编辑了我的帖子。
  • @JacobCooper:您也可以将sigma 传递给curve_fit(有关详细信息,请参阅链接文档)。
  • 太棒了!非常感谢!
猜你喜欢
  • 1970-01-01
  • 2019-07-07
  • 2018-01-13
  • 2020-07-21
  • 2015-12-12
  • 2016-08-25
  • 2019-03-28
  • 2015-10-17
  • 2016-06-20
相关资源
最近更新 更多