簡體   English   中英

使用curve_fit擬合曲線和總和

[英]Fit a curve with a sum using curve_fit

我在用 scipy 擬合曲線時遇到問題。 這是我想將我的數據放入的方程:

方程

這是代碼:

import numpy as np
import os
from mpmath import *
from pandas import read_csv
from scipy.optimize import curve_fit
from matplotlib import pyplot
from sympy import *


M = 0.0129
L = 0.006
PI = np.pi

mp.dps=10


data = np.genfromtxt('Daten.csv',dtype=float,delimiter=',')

x = data[1:,0]
y = data[1:,0]

def objective(x,Mps,B,k,D):

    return (M-Mps)*(1-np.exp(-k*x))+ Mps*(-np.exp(-B*x)*np.power(D/(B*L*L),0.5)*np.power(np.tan((B*L*L)/D),0.5)- (8/(PI*PI))*\

nsum(lambda n: np.exp(-(2*n+1)*(2*n+1)*PI*PI*D*x/(4*L*L))/((2*n+1)*(2*n+1)*(1-(2*n+2)*(2*n+2)*(D*PI*PI/(4*B*L*L)))) ,[0,float('inf')]))


def obtainpar(x,y)
    popt,_ = curve_fit(objective,x,y)

    print '{Mps,B,k,D}=', popt

然后我收到以下消息:

Traceback (most recent call last):
  File "C:/Users/gerardo.salazar/Desktop/hector.py", line 29, in <module>
    popt,_ = curve_fit(objective,x,y)
  File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 763, in curve_fit
    res = leastsq(func, p0, Dfun=jac, full_output=1, **kwargs)
  File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 388, in leastsq
    shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
  File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 26, in _check_func
    res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
  File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 463, in func_wrapped
    return func(xdata, *params) - ydata
  File "C:/Users/gerardo.salazar/Desktop/hector.py", line 27, in objective
    nsum(lambda n: np.exp(-(2*n+1)*(2*n+1)*PI*PI*D*x/(4*L*L))/((2*n+1)*(2*n+1)*(1-(2*n+2)*(2*n+2)*(D*PI*PI/(4*B*L*L)))) ,[0,float('inf')]))
  File "C:\ProgramData\Anaconda3\lib\site-packages\mpmath\calculus\extrapolation.py", line 1718, in nsum
    return +ctx.adaptive_extrapolation(update, emfun, options)
  File "C:\ProgramData\Anaconda3\lib\site-packages\mpmath\calculus\extrapolation.py", line 1165, in adaptive_extrapolation
    update(partial, xrange(index, index+step))
  File "C:\ProgramData\Anaconda3\lib\site-packages\mpmath\calculus\extrapolation.py", line 1706, in update
    psum = psum + g(ctx.mpf(k))
  File "C:\ProgramData\Anaconda3\lib\site-packages\mpmath\calculus\extrapolation.py", line 1753, in g
    return f(*args)
  File "C:\ProgramData\Anaconda3\lib\site-packages\mpmath\calculus\extrapolation.py", line 1808, in g
    return f(*args)
  File "C:/Users/gerardo.salazar/Desktop/hector.py", line 27, in <lambda>
    nsum(lambda n: np.exp(-(2*n+1)*(2*n+1)*PI*PI*D*x/(4*L*L))/((2*n+1)*(2*n+1)*(1-(2*n+2)*(2*n+2)*(D*PI*PI/(4*B*L*L)))) ,[0,float('inf')]))
TypeError: loop of ufunc does not support argument 0 of type mpf which has no callable exp method

我不能分享數據,但它只是一個簡單的 (x,y) 點,沒什么特別的。 感謝您的幫助和建議,我該如何做到這一點。

正如@piterbarg 所提到的,混合numpympmath存在幾個問題。 我的想法是保留mpmath並在計算值后換成numpy curve_fit等發送 numpy arrays ,這樣我必須照顧可迭代的 object。 最后,事實證明負DB是一個問題。 當然,不要設置邊界,而是使用 function 內部的絕對值。 因此,結果可能是負面的……但不是。

稍微清理並相應地增加代碼如下所示:

import matplotlib.pyplot as plt
import numpy as np
from mpmath import pi as PI
from mpmath import nsum
from mpmath import exp
from mpmath import sqrt
from mpmath import tan
from scipy.optimize import curve_fit
from matplotlib import pyplot

M = 0.0129
L = 0.006

### might be of interest to:
# ~import mpmath
# ~mpmath.dps=10

def objective( x, Mps, b, k, d ):
    if isinstance( x, ( list, tuple, np.ndarray ) ):
        out = np.fromiter( 
            ( objective( item, Mps, b, k, d ) for item in x ), 
            np.float 
        ) ## always return np.array
    else:
        D = abs( d ) ### fails for neg
        B = abs( b ) ### fails for neg
        dil2 = D / L**2
        out = ( M - Mps ) * ( 1 - exp( -k * x ) )
        out += Mps * ( 
            -exp( -B * x ) * sqrt( dil2 / B ) 
            * sqrt( tan( B / dil2 ) ) 
            -8 / PI**2 
            * nsum( lambda n: 
                exp( -( 2 * n + 1 )**2 * PI**2 * dil2 * x / 4 ) / (
                    ( 2 * n + 1 )**2 * ( 1 - ( 2 * n + 2 )**2
                    * ( dil2 * PI**2 / ( 4 * B ) ) )
                ), [ 0, float( 'inf' ) ]
            )
        )
    return out

############ test
xl = np.linspace( -3, 15, 55 )
yl = objective( xl, 0.5, 1, 0.3, 1.2 )
yl *= np.random.normal( loc=1, scale=0.1, size=len( yl ) )


popt, pcov = curve_fit( objective, xl, yl, p0=[ 1, 1, 1, 1 ] )
print( popt )
print( pcov ) 
### always look at pcov
### shows that fit is basically insenitive to parameter D

xfull = np.linspace( -3, 15, 155 )
yfull = objective( xfull, *popt )

fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1 )

ax.plot( xl, yl, ls='', marker='o' )
ax.plot( xfull, yfull )

plt.show()

請注意,通過*導入所有內容通常是個壞主意。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM