Python 使用SciPy'进行曲线拟合;s最小二乘法()

Python 使用SciPy'进行曲线拟合;s最小二乘法(),python,scipy,curve-fitting,Python,Scipy,Curve Fitting,我正在用Python进行最小二乘曲线拟合,得到了不错的结果,但希望它更健壮一些 我有来自一阶LTI系统的数据,更具体地说是测速仪读取的电机速度。我试图拟合电机的阶跃响应,这样我就可以推导出它的传递函数 速度(v(t))具有以下形式: v(t)=K*(1-exp(-t/t)) 不过,我使用的数据中存在一些异常值,我希望减轻这些异常值。这主要发生在速度保持恒定时。假设速度是10000个单位,我有时会得到10000+/-400的异常值。我想知道如何设置我的f_刻度参数,因为我希望我的数据点保持在“实际

我正在用Python进行最小二乘曲线拟合,得到了不错的结果,但希望它更健壮一些

我有来自一阶LTI系统的数据,更具体地说是测速仪读取的电机速度。我试图拟合电机的阶跃响应,这样我就可以推导出它的传递函数

速度(v(t))具有以下形式: v(t)=K*(1-exp(-t/t))

不过,我使用的数据中存在一些异常值,我希望减轻这些异常值。这主要发生在速度保持恒定时。假设速度是10000个单位,我有时会得到10000+/-400的异常值。我想知道如何设置我的f_刻度参数,因为我希望我的数据点保持在“实际”速度(平均值)的+/-400范围内。我应该将f_刻度设置为400还是800?我不确定我到底应该在那里设置什么

谢谢

编辑:一些数据。

我构造了一个与您的曲线相似的最小示例。如果你发布的是真实的数据而不是图片,这会更快一些。关于使用
最小二乘法进行稳健拟合,需要了解的两个关键问题是
损耗
参数必须使用不同于线性的值,并且
f_scale
用作损耗函数的缩放参数

基本上,从文档中,
least_squares
尝试

minimize F(x) = 0.5 * sum(rho(f_i(x)**2)
并在上述公式中设置损耗
loss
参数变化
rho
。对于
loss='linear'
rho
只是身份函数。当
loss='soft_l1'
时,
rho(z)=2*((1+z)**0.5-1)
f_scale
用于缩放损失函数,以便
rho_(f**2)=C**2*rho(f**2/C**2)
。因此,它不像你上面所要求的那样具有同样的意义,它更像是一种惩罚更大错误的方式

但在这种特殊情况下,这似乎没有多大区别

import numpy
import matplotlib.pyplot as plt
import scipy.optimize

tmax = 6000
N = 100
K = 6000
T = 200

smootht = numpy.linspace(0, tmax, 1000)
tm = numpy.linspace(0, tmax, N)

def f(t, K, T):
    return K * (1 - numpy.exp(-t/T))

v = f(smootht, K, T)

vm = f(tm, K, T) + numpy.random.randn(N)*400

def error(pars):
    K, T = pars
    vp = f(tm, K, T)
    return vm - vp

f_scales = [0.01, 1, 100]

plt.scatter(tm, vm)
for f_scale in f_scales:
    r = scipy.optimize.least_squares(error, [10, 10], loss='soft_l1', f_scale=f_scale)
    vp = f(smootht, *r.x)
    plt.plot(smootht, vp, label=f_scale)
plt.legend()
生成的绘图如下所示:


我的建议是在玩
f_scale

之前先尝试不同的损失函数,我已经构建了一个与你的曲线相似的最小示例。如果你发布的是真实的数据而不是图片,这会更快一些。关于使用
最小二乘法进行稳健拟合,需要了解的两个关键问题是
损耗
参数必须使用不同于线性的值,并且
f_scale
用作损耗函数的缩放参数

基本上,从文档中,
least_squares
尝试

minimize F(x) = 0.5 * sum(rho(f_i(x)**2)
并在上述公式中设置损耗
loss
参数变化
rho
。对于
loss='linear'
rho
只是身份函数。当
loss='soft_l1'
时,
rho(z)=2*((1+z)**0.5-1)
f_scale
用于缩放损失函数,以便
rho_(f**2)=C**2*rho(f**2/C**2)
。因此,它不像你上面所要求的那样具有同样的意义,它更像是一种惩罚更大错误的方式

但在这种特殊情况下,这似乎没有多大区别

import numpy
import matplotlib.pyplot as plt
import scipy.optimize

tmax = 6000
N = 100
K = 6000
T = 200

smootht = numpy.linspace(0, tmax, 1000)
tm = numpy.linspace(0, tmax, N)

def f(t, K, T):
    return K * (1 - numpy.exp(-t/T))

v = f(smootht, K, T)

vm = f(tm, K, T) + numpy.random.randn(N)*400

def error(pars):
    K, T = pars
    vp = f(tm, K, T)
    return vm - vp

f_scales = [0.01, 1, 100]

plt.scatter(tm, vm)
for f_scale in f_scales:
    r = scipy.optimize.least_squares(error, [10, 10], loss='soft_l1', f_scale=f_scale)
    vp = f(smootht, *r.x)
    plt.plot(smootht, vp, label=f_scale)
plt.legend()
生成的绘图如下所示:


我的建议是,在玩
f_scale

之前,先尝试不同的损失函数,如果你发布代码和数据,我们可以在提出建议之前复制你的结果,你会有更多的运气。我可以发布一张图,但我的问题主要是关于f_标度与裕度的关系,我想确定什么是噪声,什么是正确的数据。基本上只是f_scale=margin,f_scale=margin^2,等等。老实说,我对文档有点困惑。图片很有用,但实际数据会更好。目前还不清楚您的错误是否系统性地大于“实际”值。如果您发布代码和数据,以便我们可以在提出建议之前复制您的结果,您的运气会好得多。我可以发布一个图形,但我的问题主要是关于f_标度与裕度的关系,我想确定什么是噪声,什么是正确的数据。基本上只是f_scale=margin,f_scale=margin^2,等等。老实说,我对文档有点困惑。图片很有用,但实际数据会更好。不清楚您的误差是否系统地大于“实际”值。谢谢。我现在有点明白了,它更像是一个参数,用来减少异常值的权重。当我这么做的时候,你知道我如何计算简化卡方来确定拟合的好坏吗?无论如何,谢谢你抽出时间。谢谢。我现在有点明白了,它更像是一个参数,用来减少异常值的权重。当我这么做的时候,你知道我如何计算简化卡方来确定拟合的好坏吗?无论如何,谢谢你抽出时间。