我正在用Python进行最小的方形曲线拟合并得到不错的结果,但希望它更健壮。
我有来自一阶LTI系统的数据,更具体地说是由测速计读取的电机的速度。我正在尝试适应电机的阶跃响应,因此我可以推断出它的传递函数。
速度(v(t))具有以下形式: v(t)= K *(1 - exp(-t / T))
我在使用的数据中有一些异常值,并希望减轻它们。这主要发生在速度恒定时。假设速度是10000单位,我有时得到10000 +/- 400的异常值。我想知道如何设置我的f_scale参数给定我希望我的数据点保持在“实际”速度(平均值)的+/- 400之内。我应该将f_scale设置为400还是800?我不确定我应该在那里设置什么。
由于
答案 0 :(得分:2)
我构建了一个最小的例子,用于与你的曲线相似的曲线。如果您发布了实际数据而不是图片,那么这会更快一些。关于使用least_squares
进行稳健拟合的两个关键要点是,您必须为loss
参数使用不同于线性的值,并将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
之前先尝试不同的损失功能。