Anpassen von zwei unterschiedlichen Gleichungen an eine Funktion (kurve_fit)

Nov 23 2020

Ich habe ein Problem: Ich habe zwei verschiedene Gleichungen, eine ist eine lineare Gleichung, die andere ist eine Exponentialgleichung. Es sollten jedoch nicht beide Gleichungen gleichzeitig gültig sein, was bedeutet, dass es zwei unterschiedliche Regime gibt.

Equation 1 (x < a): E*x
Equation 2 (x >=a): a+b*x+c*(1-np.exp(-d*np.array(x)))

Das heißt, der erste Teil der Daten sollte nur mit einer linearen Gleichung und der Rest mit der zuvor erwähnten Gleichung 2 übereinstimmen.

Die Daten, die ich anpassen möchte, sehen folgendermaßen aus (ich habe auch einige Beispieldaten hinzugefügt, wenn die Leute es versuchen möchten):

Ich habe bereits mehrere Dinge ausprobiert, indem ich nur eine Anpassungsfunktion mit einer Heaviside-Funktion definiert habe:

def fit_fun(x,a,b,c,d,E):
    
    funktion1=E*np.array(x)
    
    funktion2=a+b*x+c*(1-np.exp(-d*np.array(x)))
           
    return np.heaviside(x+a,0)*funktion2+(1-np.heaviside(x+a,0))*funktion1

Definieren einer stückweisen Funktion:

def fit_fun(x,a,b,c,d,E):
    return np.piecewise(x, [x <= a, x > a], [lambda x: E*np.array(x), lambda x: a+b*x+c*(1-np.exp(-d*np.array(x)))])

zum Schluss (was bringt mir unglücklicherweise einen Formfunktionsfehler?):

def plast_fun(x,a,b,c,d,E):
   
    out = E*x
    out [np.where(x >= a)] = a+b*x+c*(1-np.exp(-d+x))
    
    return out

Versteh mich nicht falsch, ich bekomme "einige" Anfälle, aber sie scheinen entweder die eine oder die andere Gleichung zu nehmen und nicht wirklich beide zu verwenden. Ich habe auch versucht, mehrere Grenzen und anfängliche Vermutungen zu verwenden, aber es ändert sich nie.

Jede Eingabe wäre sehr dankbar!

Daten:

0.000000     -1.570670 
0.000434     83.292677 
0.000867     108.909402 
0.001301     124.121676 
0.001734     138.187659 
0.002168     151.278839 
0.002601     163.160478 
0.003035     174.255626 
0.003468     185.035092 
0.003902     195.629820 
0.004336     205.887161 
0.004769     215.611995 
0.005203     224.752083 
0.005636     233.436680 
0.006070     241.897851 
0.006503     250.352697 
0.006937     258.915168 
0.007370     267.569337 
0.007804     276.199005 
0.008237     284.646778 
0.008671     292.772349 
0.009105     300.489611 
0.009538     307.776858 
0.009972     314.666291 
0.010405     321.224211 
0.010839     327.531594 
0.011272     333.669261 
0.011706     339.706420 
0.012139     345.689265 
0.012573     351.628362 
0.013007     357.488150 
0.013440     363.185771 
0.013874     368.606298 
0.014307     373.635696 
0.014741     378.203192 
0.015174     382.315634 
0.015608     386.064126 
0.016041     389.592120 
0.016475     393.033854 
0.016908     396.454226 
0.017342     399.831519 
0.017776     403.107084 
0.018209     406.277016 
0.018643     409.441119 
0.019076     412.710982 
0.019510     415.987331 
0.019943     418.873140 
0.020377     421.178098 
0.020810     423.756827 

Bisher habe ich diese beiden Fragen gefunden, aber ich konnte es nicht herausfinden: Anpassung zweier verschiedener Funktionen mit Boarder als Anpassungsparameter Passen Sie eine Kurve für Daten an, die aus zwei unterschiedlichen Regimen bestehen

Antworten

2 FlavioMoraes Nov 23 2020 at 23:35

Ich vermute, Sie machen einen Fehler in der zweiten Gleichung, wo Sie es tun a+b*x+c*(1-np.exp(-d+x)). Wo aist der Wert, an xdem Sie von einer Kurve zur anderen wechseln? Ich denke, Sie sollten ystattdessen den Wert von verwenden, der ist a*E. Es ist auch sehr wichtig, Anfangsparameter für die Anpassung zu definieren. Ich habe den folgenden Code mit Ihren Daten in der TXT-Datei ausgeführt und die Anpassung scheint ziemlich gut zu sein, wie Sie unten sehen können:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import optimize, stats

def fit_fun(x,a,b,c,d,E):
    return np.piecewise(x, [x <= a, x > a], [lambda x: E*x, lambda x: a*E+b*x+c*(1-np.exp(-d*x))])

df = pd.read_csv('teste.txt', delimiter='\s+', header=None)
df.columns = ['x','y']

xdata = df['x']
ydata = df['y']

p0 = [0.001,1,1,1,100000]
popt, pcov = optimize.curve_fit(fit_fun, xdata.values, ydata.values, p0=p0, maxfev=10000, absolute_sigma=True, method='trf')
print(popt)

plt.plot(xdata, ydata,'*')
plt.plot(xdata, fit_fun(xdata.values, *popt), 'r')
plt.show()