Python 2.7中的非线性拟合不会给出任何好的结果

时间:2016-05-25 15:09:26

标签: python scipy curve-fitting

这是我的问题:我有实验数据以适应模型。为此,我使用了scipy中的curve_fit。脚本没有任何错误或警告,但没有给出令人满意的结果(它给了我一条准线而不是两个洛伦兹形图)。

但最奇怪的是,当我给拟合函数一个猜测数组时,没有任何猜测的参数被修改,除了第三个(尽管它远离预期的值)。但是我注意猜测参数的顺序。

我给你一些合适的代码。

X = 927.
Z = 88.
M = 5.e-15
O1 = 92975.
O2 = 93570.
bm = np.arctan2(Z,X)
P0 = 0.
T = np.pi/2.
TM = np.pi/3.
G = 20.

File ="Data.txt"
open(File,  "rb")
dat = np.loadtxt(File)

O = dat[:,1]

D = np.sqrt(1./20. *10**(dat[:,7]/10.)*1/((X**2+Z**2)*10**(6)))

def model(W,o1,o2,p0,t,tm,g):

    DB = np.abs((1./M)*(np.cos(bm-tm)*(p0*np.cos(t-tm)/(o1**2-W**2-1.j*g*W))+np.sin(bm-tm)*(p0*np.sin(t-tm)/((o2**2-W**2-1.j*g*W)))))

    return DB

guess = np.array([O1,O2,P0,T,TM,G])
fit , pcov = curve_fit(model, O , D , guess)

我在整个月内搜索一项研究,以发现任何错误,但仍然注意到。函数是否可能为curve_fit复杂化?

提前感谢您的帮助。如果您需要更多信息或数据,请不要犹豫

以下是O v D的情节。红点是实验,蓝线是返回拟合参数的函数(未修改,因此它们是猜测值)

D = model(O)

enter image description here

2 个答案:

答案 0 :(得分:0)

很难说出常量和非常长公式的混合情况。但有几点需要考虑:

  1. 如果变量没有从初始值改变,则应该注意缩放。你的X**2+Z**2)*10**(6)将在1e16左右,这可能会使得很难做出好的数字导数。你可能需要修改发送到epsfcn的{​​{1}}的值。

    < / LI>
  2. 看起来你的模型函数计算一个复杂的数组。我相信curve_fit()只能处理严格的实数值。

  3. 您可能会发现leastsq()模块很有用。

答案 1 :(得分:0)

好的人,谢谢你,我终于找到了解决方案!

而不是使用curve_fit,我尝试在this tutorial之后直接使用leastsq以查看会发生什么。它的效果比预期的要好,因为拟合确实成功并且给了我正确的峰值位置和振幅。我给你纠正的代码,因为它对我有用。

X = 927.0
Z = 88.
M = 5.e-15
O1 = 92975.
O2 = 93570.
bm = np.arctan2(Z,X)
P0=1.e-12
T=np.pi/2.
TM=np.pi/3.
G=20.

File ="Data.csv"
open(File,  "rb")
dat = np.loadtxt(File)

O = dat[:,1]

D = np.sqrt(1/1000. *10**(dat[:,7]/10.)*50.*1/((X**2+Z**2)*10**(6)))

def resid(p, y, W) :
    o1,o2,p0,t,tm,g = p
    err=y-(np.abs((1./M)*(np.cos(bm-tm)*(p0*np.cos(t-tm)/(o1**2-W**2-1.j*g*W))+np.sin(bm-tm)*(p0*np.sin(t-tm)/((o2**2-W**2-1.j*g*W))))))
    return err

def peval(W,p) :
    return np.abs((1./M)*(np.cos(bm-p[4])*(p[2]*np.cos(p[3]-p[4])/(p[0]**2-W**2-1.j*p[5]*W))+np.sin(bm-p[4])*(p[2]*np.sin(p[3]-p[4])/((p[1]**2-W**2-1.j*p[5]*W)))))


guess = np.array([O1,O2,P0,T,TM,G])
plsq = leastsq(resid,guess,args=(D,O))
print plsq[0]

plt.yscale('log')

再次感谢您的关注