2016-12-14 3 views
0

Ich habe eine Frage über die Anpassung einer Schrittfunktion mit scipy Routinen wie curve_fit. Ich habe Probleme machen es vektorisiert, zum Beispiel:wie passen Sie eine Schrittfunktion in Python

import numpy as np 
from scipy.optimize import curve_fit 
import matplotlib.pyplot as plt 

xobs=np.linspace(0,10,100) 
yl=np.random.rand(50); yr=np.random.rand(50)+100 
yobs=np.concatenate((yl,yr),axis=0) 

def model(x,rf,T1,T2): 
#1: x=np.vectorize(x) 
    if x<rf: 
     ret= T1 
    else: 
     ret= T2 
    return ret 
#2: model=np.vectorize(model) 
popt, pcov = curve_fit(model, xobs, yobs, [40.,0.,100.]) 

Es sagt

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 

Wenn ich # 1 hinzufügen oder # 2 läuft es aber passt nicht wirklich die Daten:

OptimizeWarning: Covariance of the parameters could not be estimated  category=OptimizeWarning) 
[ 40.   50.51182064 50.51182064] [[ inf inf inf] 
[ inf inf inf] 
[ inf inf inf]] 

Weiß jemand, wie man das repariert? THX

+0

vielleicht 'jobs' ->' yobs'? – MMF

+0

Was steht '[40, 0., 100.]'? – MMF

+1

In der Modellfunktion ist der Komparator (x

Antwort

1

Hier ist was ich getan habe. Ich behielt xobs und yobs:

import numpy as np 
from scipy.optimize import curve_fit 
import matplotlib.pyplot as plt 

xobs=np.linspace(0,10,100) 
yl=np.random.rand(50); yr=np.random.rand(50)+100 
yobs=np.concatenate((yl,yr),axis=0) 

Nun muss Heaviside-Funktion erzeugt werden. Um Ihnen einen Überblick über diese Funktion, betrachten die Halb maximale Konvention von Heaviside-Funktion:

Heaviside

In Python, dies entspricht: def f(x): return 0.5 * (np.sign(x) + 1)

Eine Probe Grundstück wäre:

xval = sorted(np.concatenate([np.linspace(-5,5,100),[0]])) # includes x = 0 
yval = f(xval) 
plt.plot(xval,yval,'ko-') 
plt.ylim(-0.1,1.1) 
plt.xlabel('x',size=18) 
plt.ylabel('H(x)',size=20) 

Heaviside2

Jetzt, Plotten xobs und 012.345.ergibt:

plt.plot(xobs,yobs,'ko-') 
plt.ylim(-10,110) 
plt.xlabel('xobs',size=18) 
plt.ylabel('yobs',size=20) 

xobs_yobs

bemerkt, dass die beiden Zahlen zu vergleichen, der zweite Plot von 5 Einheiten verschoben wird, und der maximalen Anstieg von 1,0 bis 100 I ableiten, dass die Funktion für die zweite Handlung sein kann wie folgt dargestellt:

Hfit

oder in Python:

(0.5 * (np.sign(x-5) + 1) * 100 = 50 * (np.sign(x-5) + 1)

Kombination der Plots Ausbeuten (wo Fit die oben Anpassungsfunktion darstellt)

Heaviside_combined

Die Handlung bestätigt, dass meine Vermutung richtig ist. Nun, unter der Annahme, dass Sie nicht wissen, wie diese korrekte Anpassungsfunktion zustande gekommen ist, wird eine verallgemeinerte Anpassungsfunktion erstellt: def f(x,a,b,c): return a * (np.sign(x-b) + c), wobei theoretisch a = 50, b = 5, und .

Gehen Sie zur Schätzung:

popt,pcov=curve_fit(f,xobs,yobs,bounds=([49,4.75,0],[50,5,2])).

Jetzt bounds = ([lower bound of each parameter (a,b,c)],[upper bound of each parameter]). Technisch bedeutet dies, dass 2. < c < 2.

Hier sind meine Ergebnisse für popt und pcov: Results

pcov die geschätzte Kovarianz von popt darstellt. Die Diagonalen liefern die Varianz der Parameterschätzung [Source].

Die Ergebnisse zeigen, dass die Parameterschätzungen pcov nahe den theoretischen Werten liegen.

Grundsätzlich ist eine generali Heaviside-Funktion kann dargestellt werden durch: a * (np.sign(x-b) + c)

Hier ist der Code, der Parameterschätzungen und die entsprechenden Kovarianzen generieren:

import numpy as np 
from scipy.optimize import curve_fit 

xobs = np.linspace(0,10,100) 
yl = np.random.rand(50); yr=np.random.rand(50)+100 
yobs = np.concatenate((yl,yr),axis=0) 

def f(x,a,b,c): return a * (np.sign(x-b) + c) # Heaviside fitting function 

popt, pcov = curve_fit(f,xobs,yobs,bounds=([49,4.75,0],[50,5,2])) 
print 'popt = %s' % popt 
print 'pcov = \n %s' % pcov 

Schließlich ist zu beachten, dass die Schätzungen von popt und pcov variieren.

+0

Sehr klare Antwort! Beeindruckend ! –

Verwandte Themen