为什么scipy.optimize.curve_fit不能正确拟合数据?

4

我一直在尝试使用 scipy.optimize.curve_fit 对一些数据进行函数拟合,但是我遇到了很大的困难。我真的看不出为什么这样不起作用。

# encoding: utf-8
from __future__ import (print_function,
                        division,
                        unicode_literals,
                        absolute_import,
                        with_statement)
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as mpl

x, y, e_y = np.loadtxt('data.txt', unpack=True)

def f(x, a, k):
    return (1/(np.sqrt(1 + a*((k-x)**2))))

popt, pcov = curve_fit(f, x, y, maxfev = 100000000)

mpl.plot(x, f(x, *popt), 'r-', label='Fit')
mpl.plot(x, y, 'rx', label='Original')
mpl.legend(loc='best')
mpl.savefig('curve.pdf')
print(popt)

# correct values which should be calculated
# a=0.003097
# k=35.4

这是由上面的代码生成的图像: enter image description here
data.txt:
#x      y       e_y
4.4     0.79    0.13
19.7    4.9     0.8
23.5    7.3     1.2
29.7    17      2.79
30.7    21.5    3.52
34      81      13.28
34.6    145     23.77
35.4    610     100
36.3    115     18.85
38.1    38      6.23
43.7    14      2.3
56.2    6.2     1.02
64.7    4.6     0.75
79.9    3.2     0.52
210     0.98    0.16

f 是什么类型的函数? - Juh_
你为什么选择 curve_fit 作为优化器? - Juh_
1
@Juh_ 我选择了 curve_fit,因为我不知道其他的替代方法。也许你可以告诉我,哪个优化器会更好一些。谢谢。 - user2870269
我的问题点在于选择优化方式与需要进行优化的问题(f&数据)有关。Greg的回答很好。 - Juh_
2个回答

16

首先尝试不要将maxfev设置得太大,这通常是其他问题的表现!通过以下添加,我可以得到一个适合的匹配:

def f(x, b, a, k):
    return (b/(np.sqrt(1 + a*((k-x)**2))))

popt, pcov = curve_fit(f, x, y, p0=[20, 600.0, 35.0])

首先,您提供的拟合函数的最大值为1,由于数据中的峰值为600,因此它永远不会适合。因此,我添加了一个整体因子b。其次,试着帮助可怜的老curve_fit。如果您可以通过肉眼看到它在x~35处达到峰值,则要通过p0告诉它。这需要一些对函数如何工作的直觉,但如果要使用曲线拟合函数,则非常重要。

enter image description here


@Greg 你好,感谢你的出色回答。我理解了你的解释。不幸的是,我被迫使用给定的函数,这意味着你的附加因子 b 必须为1。在这个练习中,我不能改变它。也许你可以告诉我另一种方法来获得代码中已经提到的正确值 ak。谢谢。 - user2870269
@Greg 对不起,你是完全正确的。给定的函数是“错误”的,永远不会适合这些数据。无法解决的、不正确的练习真的很烦人。感谢你的帮助! - user2870269
1
Marsch,我认为问题中可能缺少一些内容。如果您对数据进行规范化,则此函数将正常工作,它是否要求您对其进行规范化?如果没有,则应该提供带有b的函数或要求您对其进行规范化。 - Greg

1
我在X-Y散点图上查看了原始数据,发现拟合这些数据需要一个非常尖锐、狭窄的峰值方程。你所得到的方程无法产生峰值响应。据我看来,将这些数据拟合到给定的方程中是行不通的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接