我正在尝试使用scipy.optimize.leastsq来适应步骤函数。请考虑以下示例:
import numpy as np
from scipy.optimize import leastsq
def fitfunc(p, x):
y = np.zeros(x.shape)
y[x < p[0]] = p[1]
y[p[0] < x] = p[2]
return y
errfunc = lambda p, x, y: fitfunc(p, x) - y # Distance to the target function
x = np.arange(1000)
y = np.random.random(1000)
y[x < 250.] -= 10
p0 = [500.,0.,0.]
p1, success = leastsq(errfunc, p0, args=(x, y))
print p1
参数是步骤的位置和两侧的水平。奇怪的是,第一个自由参数永远不会变化,如果你运行那个scipy会给出
[ 5.00000000e+02 -4.49410173e+00 4.88624449e-01]
当第一个参数设置为250时最佳,第二个参数设置为-10。
有没有人知道为什么这可能不起作用以及如何让它发挥作用?
如果我跑
print np.sum(errfunc(p1, x, y)**2.)
print np.sum(errfunc([250.,-10.,0.], x, y)**2.)
我发现:
12547.1054663
320.679545235
其中第一个数字是leastsq找到的数字,第二个数字是它应该找到的实际最佳函数的值。
答案 0 :(得分:2)
事实证明,如果我将epsfcn =参数添加到leastsq,拟合会好得多:
p1, success = leastsq(errfunc, p0, args=(x, y), epsfcn=10.)
,结果是
[ 248.00000146 -8.8273455 0.40818216]
我的基本理解是第一个自由参数必须移动多于相邻点之间的间距以影响残差的平方,而epsfcn与用于查找渐变的大步骤有关,或者某些东西类似。
答案 1 :(得分:1)
我不认为最小二乘拟合是一种方法来提出一个步骤的近似值。我不相信它会给你一个令人满意的不连续性描述。在攻击这个问题时,最不正确的方块不是我的第一个想法。
为什么不使用傅立叶级数近似?在不连续的情况下,你总是会遇到Gibbs的现象,但是你和你的CPU能够负担得起功能的其余部分。
你究竟打算用它做什么?一些上下文可能有所帮助。
答案 2 :(得分:1)
我建议近似阶梯函数。代替 “变化点”处的无限斜率使其成为线性的 一个x距离(示例中为1.0)。例如。如果是x 函数的参数xp定义为中点 在这一行上,xp-0.5的值是较低的y值 并且xp + 0.5处的值是更高的y值和 函数的中间值 区间[xp-0.5; xp + 0.5]是线性的 这两点之间的插值。
如果可以假设步进功能(或其功能) 近似值从较低值到较高值 然后我想最后两个参数的初始猜测 应该是最低的y值和最高的y值 分别代替0.0和0.0。
我有两个更正:
1)np.random.random()返回范围内的随机数 0.0到1.0。因此,平均值是+0.5,也是值的 第三个参数(而不是0.0)。第二个参数 然后是-9.5(+0.5 - 10.0)而不是-10.0。
因此
print np.sum(errfunc([250.,-10.,0.], x, y)**2.)
应该是
print np.sum(errfunc([250.,-9.5,0.5], x, y)**2.)
2)在原始的fitfunc()中,如果x,则y的一个值变为0.0 完全等于p [0]。因此它不是一个阶梯函数 那种情况(更像是两步功能的总和)。例如。这个 当第一个参数的起始值为500时发生。
答案 3 :(得分:0)
很可能您的优化卡在本地最小值中。我不知道什么是最小的,但是如果给它一个初始估计值(0,0,0),它也会卡在那里。
你可以用初始估计数字检查梯度(在+/- epsilon处评估一个非常小的epsilon并除以bei 2 * epsilon,取差异)并且我打赌它将在0附近。
答案 4 :(得分:0)
使用 statsmodel ols。 ols 使用普通最小二乘法进行曲线拟合