scipy.optimize.curve_fit:无法进行曲线拟合

时间:2013-12-14 22:44:31

标签: python

我仍然是python的新手,我有一个问题机智曲线拟合。以下程序是我创建的更大程序的简化,但它代表了我所遇到的问题。

问题在于我有一个我称汉堡的功能,我无法适应曲线。这一行:y = np.sqrt(y):是个问题。当我删除它时,我可以完美地适应它,但这不是我想要的功能。

我如何拟合这个函数y = np.sqrt(y)?

# -*- coding: utf-8 -*-
"""
Created on Wed Dec 11 22:14:54 2013

@author: 
"""
import numpy as np
import matplotlib.pyplot as plt
import pdb
import scipy.optimize as optimization
from math import *
from scipy.optimize import curve_fit

import math
import moyenne

####################Function Burger###############################

def burger(t, E1, E2, N,tau):
    nu=0.4 #Coefficient de Poisson
    P=50 #Peak force
    alpha=70.3 #Tip angle
    y=((((pi/2.)*P*(1.-nu**2.))/(tan(alpha)))*(1./E1 + 1./E2*(1.-np.exp(-t/tau)) + 1./((N)*(1.-nu))*t))
    y=np.sqrt(y)
    return y

#######exemple d'utilisation##########   
xlist=np.linspace(0,1,100) 
ylist=[ burger(t,3, 2,1,0.1) for t in xlist] 

#pdb.set_trace()
pa,j = curve_fit(burger,xlist,ylist)

yfit=[burger(x,*pa) for x in xlist]

plt.figure()
plt.plot(xlist,ylist,marker='o')
plt.plot(xlist,yfit)
plt.show()

1 个答案:

答案 0 :(得分:1)

所以,这可能不是你得到的最佳答案,但是当你在这里等待其他人时,需要考虑一些事情。

首先,既然你是python的新手,也许你不知道,或者也许有理由在列表理解中解决这些问题,但我认为你不需要列表推导。您可以使用numpy数学运算一次处理整个数组。而不是

    y=((((pi/2.)*P*(1.-nu**2.))/(tan(alpha)))* ...

你可以写

    y = ((((np.pi/2.)*P*(1.-nu**2.))/(np.tan(alpha)))* ...

然后代替

    [ burger(t, 3., 2., 1., 0.1) for t in xlist] 

你可以做到

    burger(xlist, 3., 2., 1., 0.1)

使用数组时,这会快得多。

其次,只是查看算法中发生的一些事情。它没有在正确的范围内寻找您的参数。我在scipy.optimize页面(here)上查找了它正在使用的算法,维基百科说收敛取决于初始猜测,并且它找到了本地而非全局的最小值(有时你的代码命中对于某些情况,使得sqrt of y undefined的参数的负值)。如果有一种方法你可以给它一个很好的初始猜测然后它应该工作([1.,3.,3.,2]为我工作)。我解决它的命令是:pa,j = curve_fit(burger,xlist,ylist, [1., 3., 3., 2], maxfev=10000))。

第三,我使用你的代码时得到的第一个错误是它达到了最大数量的fevals。添加maxfev=10000(如果需要,可以更多)作为curve_fit的最后一个参数。

检查出来。如果你可以给你一个更大的问题进行初步猜测,那么你可能会让它收敛。否则,不同的算法可能更合适?

更新:请参阅此question以获取有关其工作原理的更详细说明,但如果您再给它一个kwg diag,则无需猜测即可使用它。

使用:

    pa,j = curve_fit(burger,xlist,ylist, diag=(1./xlist.mean(), 1./ylist.mean()), maxfev=10000)