如何使用来自 SciPy 的曲线拟合将某些点优先于其他点

How to prioritise some points over others using curve fit from SciPy

我想模拟以下曲线:

为了执行它,我使用 SciPy 中的 curve_fit,拟合指数函数。

def exponenial_func(x, a, b, c):
    return a * b**(c*x)

popt, pcov = curve_fit(exponenial_func, x, y, p0=(1,2,2), 
                       bounds=((0, 0, 0), (np.inf, np.inf, np.inf)))

当我第一次这样做时,我得到了这个:

这是最小化残差,每个点具有相同的重要性。 我想要的是获得一条曲线,它更重视曲线的最后一个值(例如,从 x 轴 30 开始)而不是第一个值,因此它更适合曲线的末尾而不是开始它的。

我知道从这里开始有很多方法可以解决这个问题(首先,定义我想赋予每个残差的重要性)。我的问题是想知道如何处理这个问题。

我的一个想法是更改 sigma 值以通过其倒数对每个数据点进行加权。

popt, pcov = curve_fit(exponenial_func, x, y, p0=(1,2,2), 
                       bounds=((0, 0, 0), (np.inf, np.inf, np.inf)),
                       sigma=1/y)

在这种情况下,我得到了我正在寻找的东西:

看起来不错,但我正在寻找另一种方法,这样我就可以 "control" 每个数据点,比如以线性方式对每个残差进行加权,或指数,甚至手动选择它(而不是像前面的情况那样通过逆向选择它们)。

提前致谢

首先请注意,不需要三个系数。自

a * b**(c*x) = a * exp(log(b)*c*x).

我们可以定义k = log(b)*c

这里有一个建议,你可以如何 手动 使用 scipy.optimize.least_squares 和优先向量:

import numpy as np
from scipy.optimize import least_squares

def exponenial_func2(x, a, k):
    return a * np.exp(k*x)

# returns the vector of residuals
def fitwrapper2(coeffs, *args):
    xdata, ydata, prio = args
    return prio*(exponenial_func2(xdata, *coeffs)-ydata)

# Data
n = 31
xdata = np.arange(n)
ydata = np.array([155.0,229,322,453,655,888,1128,1694,
                  2036,2502,3089,3858,4636,5883,7375,
                  9172,10149,12462,12462,17660,21157,
                  24747,27980,31506,35713,41035,47021,
                  53578,59138,63927,69176])

# The priority vector
prio = np.ones(n)
prio[-1] = 5

res = least_squares(fitwrapper2, x0=[1.0,2.0], bounds=(0,np.inf), args=(xdata,ydata,prio))
  • 对于prio[-1] = 5,我们将最后一点放在高优先级。

  • res.x 包含您的最佳系数。这里a, k = res.x.

  • 请注意,对于 prio = np.ones(n),这是一个正常的最小二乘拟合(就像 curve_fit 那样),其中所有点都具有相同的 优先级 .

您可以通过增加 prio 数组中每个点的值来控制每个点的优先级。比较这两个结果给我: