Python 正弦幂级数的最小二乘拟合

Python 正弦幂级数的最小二乘拟合,python,numpy,scipy,mathematical-optimization,curve-fitting,Python,Numpy,Scipy,Mathematical Optimization,Curve Fitting,我试图拟合一个形式函数: 其中A和B是固定常数。在scipy中,我通常(我认为是合理的规范)处理此类问题的方法如下: def func(t, coefs): phase = np.poly1d(coefs)(t) return A * np.cos(phase) + B def fit(time, data, guess_coefs): residuals = lambda p: func(time, p) - data fit_coefs = scipy.

我试图拟合一个形式函数:

其中A和B是固定常数。在scipy中,我通常(我认为是合理的规范)处理此类问题的方法如下:

def func(t, coefs):
    phase = np.poly1d(coefs)(t)
    return A * np.cos(phase) + B

def fit(time, data, guess_coefs): 
    residuals = lambda p: func(time, p) - data
    fit_coefs = scipy.optimize.leastsq(residuals, guess_coefs) 
    return fit_coefs
这是可行的,但我想提供一个分析雅可比矩阵来改进收敛性。因此:

def jacobian(t, coefs):
    phase = np.poly1d(coefs, t)
    the_jacobian = []
    for i in np.arange(len(coefs)):
        the_jac.append(-A*np.sin(phase)*(t**i))
    return the_jac

def fit(time, data, guess_coefs):
    residuals = lambda p: func(time, p) - data
    jac = lambda p: jacobian(time, p)
    fit_coefs = scipy.optimize.leastsq(residuals, guess_coefs, 
                                       Dfun=jac, col_deriv=True)
这也不起作用,即使是在2或更少的数量级。使用optimize.check_gradient()快速检查也不会给出积极的结果

我几乎可以肯定雅可比矩阵和代码是正确的(尽管请纠正我),问题更为根本:雅可比矩阵中的t**I项会导致溢出错误。这不是函数本身的问题,因为这里的单项项乘以它们的系数,系数非常小

我的问题是:

  • 我上面所做的代码是否有错误
  • 还是有其他问题
  • 如果我的假设是正确的,有没有一种方法可以对拟合函数进行预处理,从而使雅可比矩阵表现得更好?也许我能适应数据和时间的对数,或者别的什么
  • 谢谢


    编辑:忘记了原始函数形式中的正方形,
    poly1D
    函数首先具有最高的系数,而雅可比函数首先假定最低的系数。如果在
    jacobian
    中使用return语句
    返回_jac[:-1]
    (并修复更明显的打字错误),您的函数将通过
    优化。检查_gradient()
    并在
    leastsq()
    中正确工作

    关于数值稳定性的进一步问题也在这里得到了证实。如果你有大量的t值和大量的系数,你很容易会遇到数值精度问题:例如,在32位精度中,如果你的多项式计算值超过10^8,正弦的相位将在尾数中完全丢失,正弦计算的结果基本上是垃圾


    您可以通过在多项式中使用模幂来解决这个问题:基本上,多项式的每个项都关心
    (a_k t**k)%p
    ,其中
    p=2*np.pi
    是正弦周期。对于大的
    t
    (a_k*(t%(p/a_k))**k)%p,您可以以更高的精度计算此模指数;对于一般的准确性
    k
    来说,事情变得有点复杂。请参阅,以了解有关这些内容的详细讨论。

    poly1D函数首先具有最高的系数,而雅可比函数首先假定最低的系数。如果在
    jacobian
    中使用return语句
    返回_jac[:-1]
    (并修复更明显的打字错误),您的函数将通过
    优化。检查_gradient()
    并在
    leastsq()
    中正确工作

    关于数值稳定性的进一步问题也在这里得到了证实。如果你有大量的t值和大量的系数,你很容易会遇到数值精度问题:例如,在32位精度中,如果你的多项式计算值超过10^8,正弦的相位将在尾数中完全丢失,正弦计算的结果基本上是垃圾

    您可以通过在多项式中使用模幂来解决这个问题:基本上,多项式的每个项都关心
    (a_k t**k)%p
    ,其中
    p=2*np.pi
    是正弦周期。对于大的
    t
    (a_k*(t%(p/a_k))**k)%p,您可以以更高的精度计算此模指数;对于一般的准确性
    k
    来说,事情变得有点复杂。关于这些事情,请仔细讨论