我试图将单调曲线拟合到一些近乎单调的数据上。 (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值上要容易得多,我可以这样做。)
答案 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)