1

我正在尝试将一些实验数据拟合到具有一个参数的非线性函数,该参数包括一个反余弦函数,因此它的定义区域从-1到1受到限制。我使用scipy的curve_fit来查找函数的参数,但是它返回以下错误:

RuntimeError: Optimal parameters not found: Number of calls to function has reached maxfev = 400.

我想要适合的功能是这个:

def fitfunc(x, a):
    y = np.rad2deg(np.arccos(x*np.cos(np.deg2rad(a))))
    return y

对于拟合,我分别为 x 和 y 提供了一个 numpy 数组,其中包含度数(这就是该函数包含与弧度之间的转换的原因)。

param, param_cov = curve_fit(fitfunc, xs, ys)

当我使用其他拟合函数(例如多项式)时,curve_fit 返回一些值,上述错误仅在我使用包含反余弦的此函数时发生。

我怀疑它不能拟合数据点,因为根据反余弦函数的参数,一些数据点不在反余弦的定义区域内。我尝试提高迭代次数(maxfev)但没有成功。

样本数据:

ys = np.array([113.46125, 129.4225, 140.88125, 145.80375, 145.4425, 
              146.97125, 97.8025, 112.91125, 114.4325, 119.16125, 
              130.13875, 134.63125, 129.4375, 141.99, 139.86, 
              138.77875, 137.91875, 140.71375])

xs = np.array([2.786427013, 3.325624466, 3.473013087, 3.598247534, 4.304280248,
               4.958273121, 2.679526725, 2.409388637, 2.606306639, 3.661558062,
               4.569923009, 4.836843789, 3.377013596, 3.664550526, 4.335401233,
               3.064199519, 3.97155254, 4.100567011])
4

1 回答 1

3

正如HS-nebula在他的评论中提到的,您需要定义一个初始值a0作为a曲线拟合的开始猜测。此外,您在选择时需要小心,a0因为您np.arcos()仅在 [-1,1] 中定义,选择错误a0会导致错误。

import numpy as np
from scipy.optimize import curve_fit

ys = np.array([113.46125,  129.4225, 140.88125, 145.80375,  145.4425, 146.97125,  
                 97.8025, 112.91125,  114.4325, 119.16125, 130.13875, 134.63125,
                129.4375,    141.99,    139.86, 138.77875, 137.91875, 140.71375])

xs = np.array([2.786427013, 3.325624466, 3.473013087, 3.598247534, 4.304280248, 4.958273121, 
               2.679526725, 2.409388637, 2.606306639, 3.661558062, 4.569923009, 4.836843789,
               3.377013596, 3.664550526, 4.335401233, 3.064199519, 3.97155254, 4.100567011])

def fit_func(x, a):
    a_in_rad         = np.deg2rad(a)
    cos_a_in_rad     = np.cos(a_in_rad)
    arcos_xa_product = np.arccos( x * cos_a_in_rad )
    return np.rad2deg(arcos_xa_product)

a0 = 80
param, param_cov = curve_fit(fit_func, xs, ys, a0, bounds = (0, 360))
print('Using curve we retrieve a value of a = ', param[0])

输出:

Using curve we retrieve a value of a =  100.05275506147824

但是,如果您选择a0=60,则会收到以下错误:

ValueError:残差在初始点不是有限的。

为了能够使用具有所有可能值的数据,HS-nebulaa建议的标准化是个好主意。

于 2019-06-13T22:46:53.670 回答