【问题标题】:Curve fitting with known coefficients in PythonPython中已知系数的曲线拟合
【发布时间】:2021-12-12 07:01:58
【问题描述】:

我尝试使用 Numpy、Scipy 和 Scikitlearn,但在其中任何一个中都找不到我需要的东西,基本上我需要将曲线拟合到数据集,但是将一些系数限制为已知值,我找到了如何在 MATLAB 中使用 fittype 执行此操作,但在 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 之类的东西不起作用(至少在我尝试过的情况下)。

【问题讨论】:

  • 你绝对应该看看this SO post
  • 我认为他们的问题有点不同,因为他们只知道截距系数,而我的适合“几乎所有已知的函数”,即使我认为这不是同一个问题我'一定要检查一下才能确定
  • 好吧,如果你想适应a * x**2 + b * x + c,但bc是已知的,你只需减去你的y-values ys = y - b * x - c 的信息并适应a * x**2到那个数据,例如通过 `Polinomial.fit( ..., deg=[2] )
  • 注意,此时curve_fit 可以正常工作。然而,这是一个线性拟合,而 `curve_fit,从技术上讲,是用于非线性拟合的,所以它在某种程度上不是适合这项工作的工具。但这更像是一个纯粹主义者而不是实际的观点
  • @mikuszefski 问题是我的 b 值为 0,所以 sub 不会产生影响,Poly fit 会尝试猜测它。

标签: python-3.x numpy scikit-learn data-science curve-fitting


【解决方案1】:

您可用的工具通常期望函数仅输入其参数(a 是您的唯一未知数),或输入其参数和一些数据(axy 在您的案例)。

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)

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

【讨论】:

  • 我想你让我意识到我一直需要的是我认为行不通的curve_fit,我一定会按照你展示的方式尝试它,因为它看起来真的很有效,但我真的是这方面的初学者,所以在第二个代码块之后我什么都不懂,这只是做同样事情的更高级/更精确的方式吗?因为如果是的话,我会坚持简单一点,不那么精确,如果不是,那么您是否有任何链接可以更详细地分解该主题?总的来说谢谢。
  • 这 3 个代码块是做同样事情的不同方式。第一个使用curve_fit。第二种使用最小化(稍微复杂一些,但它可以在更多情况下使用,而不仅仅是将曲线拟合到数据)。第三个创建了一个函数polyfit,它自动处理混合的已知/未知多项式系数(使用None 表示您不知道的系数),以防您碰巧做了很多此类事情。
  • ...也许 numpy.polynomial.polynomial.Polynomial 用于第 4 块?
  • 我想我们不应该使用已弃用的代码;)我最终会更新它,或者如果您愿意,可以随时编辑帖子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-20
  • 1970-01-01
  • 2012-12-16
  • 2020-12-06
相关资源
最近更新 更多