适合单调曲线(最好是在python中)

时间:2012-12-19 11:57:28

标签: python optimization curve-fitting

我试图将单调曲线拟合到一些近乎单调的数据上。 (X值是单调的,Y值应该是单调的,但噪声通常大于点到点的基础值的变化。)以下是我目前正在做的总结:

def goodness_of_fit(Xfit):
    assert(is_sorted(Xfit))
    # ( Calculate the area between the fit line and the join-the-dots line from the data )

scipy.optimize.minimize(goodness_of_fit, x0=numpy.linspace(xmin, xmax))

我找不到一种方法来获得优化算法来保持Xfit数组的排序 - 是否有人有任何建议? (数组的大小太大,无法创建N-1个别排序约束并使用约束优化函数。)如果最佳解决方案仅适用于Python,我愿意使用Python以外的其他语言那种语言。

(NB我确实拟合了X值,而不是Y值 - 这是因为我最终想要绘制dX / dY曲线,并且如果我从原始图中绘制它,它就不会爆炸到荒谬的值但是,如果将Y值拟合到固定的X值上要容易得多,我可以这样做。)

2 个答案:

答案 0 :(得分:2)

如何从Xfit创建一个严格单调子集的新数组,然后拟合曲线? 类似的东西:

Xfit      = np.hstack(((-1,-1,0,1,1),np.arange(1,10),(-7,9,10,10)))
len_mono  = 0
Xfit_mono = zeros(Xfit.size)
Xfit_mono_ind = zeros(Xfit.size)
Xfit_mono[len_mono] = Xfit[0]

for(iX, x) in enumerate(Xfit):
    if iX > 0:
        if x > Xfit_mono[len_mono]:
            len_mono = len_mono + 1
            Xfit_mono[len_mono] = x
            Xfit_mono_ind[len_mono] = iX 
Xfit_mono_ind = Xfit_mono_ind[:len_mono+1]
Xfit_mono = Xfit_mono[:len_mono+1]
print(Xfit_mono_ind)
print(Xfit_mono)

然后你可以在曲线拟合中使用Xfit_mono,当你想选择相关的y值时,可以使用Xfit_mono_ind的值作为y的索引。

更新替换:

if x > Xfit[iX-1]:

使用:

if x > Xfit_mono[len_mono]:

对于弱增加旧解决方案的工作原理。然而,如果它逐渐减少,旧的结果给出了错误的答案。此更新在两种情况下都提供了所需的结果。

答案 1 :(得分:1)

最后,我通过拟合连续X值之间的差异而不是值本身来做到这一点 - 然后我可以使用零的简单下限。

def fg(X):
    # return the objective function and its Jacobian

def adjusted_fg(X_diff):
    X = cumsum(X_diff)
    score, jac = fg(X)
    jac[1:] = np.diff(jac)
    return score, jac

X0_diff[1:] = [X0[0]] + np.diff(X0)
bounds = [(None, None)] + [(0, None) for i in range(len(X0)-1)]

scipy.optimize.minimize(adjusted_fg, X0_diff, method='L-BFGS-B', bounds=bounds)

对于大N,如果没有在解决方案附近开始,这往往是不稳定和/或陷入局部最小值,所以我将首先尝试拟合较小的N(例如N / 10),然后插值以获得更大的N适合的X0。

(N.B。对于我的问题,我实际上需要严格的排序,所以我使用了正下限而不是0)