5

我正在尝试将单调曲线拟合到一些几乎单调的数据。(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 个单独的排序约束并使用约束优化函数。)如果最佳解决方案仅在那种语言。

(注意,我确实拟合了 X 值,而不是 Y 值 - 这是因为我最终想要绘制 dX/dY 曲线,并且不会像我从原始数据中绘制它那样放大到荒谬的值。但是,如果在固定 X 值上拟合 Y 值要容易得多,我可以这样做。)

4

2 回答 2

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]:

对于弱增加的旧解决方案有效。但是,如果它一直在减少,旧的结果给出了错误的答案。此更新在这两种情况下都给出了预期的结果。

于 2012-12-19T12:50:18.597 回答
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 更好。

(注意对于我的问题,我实际上想要严格的排序,所以我使用了一个正的下限而不是 0)

于 2012-12-20T13:44:28.883 回答