【问题标题】:Better way to create fit functions with changing number of parameters in Python with Scipy curve_fit使用 Scipy curve_fit 在 Python 中通过改变参数数量创建拟合函数的更好方法
【发布时间】:2016-09-24 15:26:12
【问题描述】:

我正在寻找更好的方式来使用 scipy 的curve_fit()

我目前正在使用它来拟合参数和向量 x 的线性组合。

例如,这是我传递的一个拟合函数,用于尝试使用 5 个参数 m0-m4 进行拟合:

def degFour(x, m0, m1, m2, m3, m4):
    return x[0]*m0 + x[1]*m1 + x[2]*m2 + x[3]*m3 + x[4]*m4

我使用相同的模式制作了更多这些直到 degTen。它也确实有效。

我的 x 向量:

[[ 1.          1.          1.          1.          1.        ]
 [ 1.          0.99990931  0.99963727  0.99918392  0.99854935]
 [ 1.          0.94872591  0.80016169  0.56954235  0.28051747]
 [ 1.          0.84717487  0.43541052 -0.10943716 -0.62083535]
 [ 1.          0.77991807  0.21654439 -0.44214431 -0.90621706]
 [ 1.          0.73162055  0.07053725 -0.62840754 -0.99004899]
 [ 1.          0.68866877 -0.05147065 -0.75956123 -0.99470154]
 [ 1.          0.64892616 -0.15778967 -0.85371386 -0.95020484]
 [ 1.          0.6114128  -0.25234877 -0.91999134 -0.8726402 ]
 [ 1.          0.57600247 -0.33644232 -0.96358568 -0.77361313]
 [ 1.          0.54225052 -0.41192874 -0.98898767 -0.66062942]
 [ 1.          0.29541145 -0.82546415 -0.78311458  0.36278212]
 [ 1.          0.09546594 -0.98177251 -0.28291761  0.92775452]
 [ 1.         -0.07539697 -0.9886306   0.22447646  0.95478091]
 [ 1.         -0.22050008 -0.90275943  0.61861713  0.62994918]
 [ 1.         -0.33964821 -0.76927818  0.86221613  0.18357784]
 [ 1.         -0.54483185 -0.40631651  0.9875802  -0.66981378]
 [ 1.         -0.71937092  0.03498904  0.66903073 -0.99755153]
 [ 1.         -1.          1.         -1.          1.        ]]

我的数据:

[  3.50032   3.5007    3.6328    3.94564   4.12814   4.2651    4.39586
   4.51982   4.64394   4.76738   4.88654   5.90314   6.93304   7.99074
   9.04278  10.02426  12.01392  14.0592   18.1689 ]

使用 curve_fit(degFour, xdata.T, ydata),我得到了正确的系数:

[ 9.14562709 -7.05004692  1.66932215 -0.27868686  0.02097462]

我根据度数重新创建 x 数据,因此我将始终以正确的形状传入数据。

我尝试了一个关于可变输入参数的fbstj's answer 版本。

我用过这个:

def vararg(x, *args):
    return sum(a * x[i] for i, a in enumerate(args))

结果是这样的:

Traceback (most recent call last):
  File "D:/Libraries/Desktop/PScratch2/vararg.py", line 18, in <module>
    print(curve_fit(vararg, deg4kary.T, deg4ydata))
  File "C:\Python35\lib\site-packages\scipy\optimize\minpack.py", line 606, in curve_fit
    raise ValueError("Unable to determine number of fit parameters.")
ValueError: Unable to determine number of fit parameters.

从跟踪中可以看出,我只是传递了函数本身。我被卡住了。

【问题讨论】:

  • 你试过使用样条吗?
  • 我在此处显示的这些数据是更大数据集的一部分。该集合被分解为子集并进行拟合。结果拟合及其一阶导数必须是分段连续的。还有其他事情在起作用,但据我所知,我必须使用这种方法。
  • 三次样条的定义是具有分段连续一阶导数的三次分段连续插值函数。我会尝试使用scipy.interpolate.InterpolatedUnivariateSplineDocumentation
  • curve_fit需要明确说出拟合参数的个数

标签: python scipy curve-fitting


【解决方案1】:

您正在为数据拟合多元线性模型。这可以表示为x 向量之间的点积,形状为(npoints, nparams),和单个(nparams,) 系数向量,比如m

def linear(x, m):
    return x.dot(m)

x = np.random.randn(100, 5)
m = np.random.randn(5)

y = linear(x, m)

确实没有必要使用curve_fit 来获得m 系数 - 使用np.linalg.lstsq 来解决这样的线性系统更简单、更有效:

m_hat, residuals, rank, singular_vals = np.linalg.lstsq(x, y)

这里,m_hat 将是一个(n_params,) 向量,其中包含m0m1m2 等的最小二乘估计值。这适用于任意数量的系数。

【讨论】:

  • 您的答案肯定比我之前实现的更优雅,但我在使用它时遇到了麻烦。例如,我从两组值开始,都是 (m,) ,然后创建一个从自变量到称为 k 的范围 [-1, 1] 的线性映射。然后我创建一个数组 (m, n),其中 n+1 是我希望使用的系数的数量,coeff_n = [0, n]。数组值为 cos(coeff_n * arccos(k))。这些列是基向量,第一个是全向量。第二个是k等...鉴于此设置,我将如何使用您的方法?谢谢。
猜你喜欢
  • 2017-04-11
  • 2016-01-16
  • 2016-03-12
  • 2021-03-19
  • 2020-05-05
  • 2021-02-16
  • 2016-09-16
  • 2017-07-13
  • 1970-01-01
相关资源
最近更新 更多