Python 中已知系数的曲线拟合

Curve fitting with known coefficients in Python

我尝试使用 Numpy、Scipy 和 Scikitlearn,但无法在其中任何一个中找到我需要的东西,基本上我需要将曲线拟合到数据集,但将一些系数限制为已知值,我找到了如何使用 fittype 在 MATLAB 中执行此操作,但无法在 python.

中执行此操作

在我的例子中,我有一个 X 和 Y 的数据集,我需要找到最佳拟合曲线,我知道它是二次多项式 (ax^2 + bx + c) 并且我知道它是 b 的值和 c,所以我只需要它来找到 a 的值。

我在MATLAB中找到的解决方案是https://www.mathworks.com/matlabcentral/answers/216688-constraining-polyfit-with-known-coefficients,这和我的问题是一样的,但不同的是它们的多项式是5次,我怎么能在python中做类似的事情呢?

要添加一些信息:我需要将曲线拟合到数据集,所以像 scipy.optimize.curve_fit 这样期望函数的东西将不起作用(至少就我尝试而言)。

您可用的工具通常期望函数仅输入其参数(a 在您的情况下是唯一未知的),或输入其参数和一些数据(ax,在你的情况下 y)。

Scipy 的曲线拟合可以很好地处理该用例,只要我们将其传递给它理解的函数即可。它首先需要 x,然后将所有参数作为剩余参数:

from scipy.optimize import curve_fit
import numpy as np

b = 0
c = 0
def f(x, a):
    return c+x*(b+x*a)

x = np.linspace(-5, 5)
y = x**2

# params == [1.]
params, _ = curve_fit(f, x, y)

或者,您可以使用您最喜欢的最小化例程。这里的区别是你手动构造误差函数,让它输入你关心的参数,然后你不需要把那个数据提供给scipy。

from scipy.optimize import minimize
import numpy as np

b = 0
c = 0

x = np.linspace(-5, 5)
y = x**2

def error(a):
    prediction = c+x*(b+x*a)
    return np.linalg.norm(prediction-y)/len(prediction)**.5

result = minimize(error, np.array([42.]))
assert result.success

# params == [1.]
params = result.x

我不认为 scipy 有内置的部分应用多项式拟合函数,但如果您经常做这种事情,您可以使用上述任一想法轻松地自己构建一个。

from scipy.optimize import curve_fit
import numpy as np

def polyfit(coefs, x, y):
    # build a mapping from null coefficient locations to locations in the function
    # coefficients we're passing to curve_fit
    # 
    # idx[j]==i means that unknown_coefs[i] belongs in coefs[j]
    _tmp = [i for i,c in enumerate(coefs) if c is None]
    idx = {j:i for i,j in enumerate(_tmp)}

    def f(x, *unknown_coefs):
        # create the entire polynomial's coefficients by filling in the unknown
        # values in the right places, using the aforementioned mapping
        p = [(unknown_coefs[idx[i]] if c is None else c) for i,c in enumerate(coefs)]
        return np.polyval(p, x)
    
    # we're passing an initial value just so that scipy knows how many parameters
    # to use
    params, _ = curve_fit(f, x, y, np.zeros((sum(c is None for c in coefs),)))

    # return all the polynomial's coefficients, not just the few we just discovered
    return np.array([(params[idx[i]] if c is None else c) for i,c in enumerate(coefs)])

x = np.linspace(-5, 5)
y = x**2

# (unknown)x^2 + 1x + 0
# params == [1, 0, 0.]
params = fit([None, 0, 0], x, y)

几乎每个主流科学图书馆都存在类似的功能;您可能只需要稍微重塑您的问题,以根据可用的基元来构建它。