3 votes

Ajustement de courbes avec un grand nombre de points de données

Il s'agit d'un problème assez spécifique pour lequel j'espérais que la communauté pourrait m'aider. Merci d'avance.

J'ai donc deux séries de données, l'une expérimentale et l'autre basée sur une équation. J'essaie d'ajuster mes points de données à cette courbe et donc d'obtenir les variables manquantes qui m'intéressent. A savoir, a et b dans la fonction Ebfit.

Voici le code :

%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as spys
from scipy.optimize import curve_fit

time = [60,220,520,1840]
Moment = [0.64227262,0.468318916,0.197100772,0.104512508]

Temperature = 25                                # Bake temperature in degrees C
Nb = len(Moment)                                           # Number of bake measurements
Baketime_a = time                  #[s]
N_Device = 10000                                    # No. of devices considered in the array
T_ambient = 273 + Temperature
kt = 0.0256*(T_ambient/298)                         # In units of eV
f0 = 1e9                                            # Attempt frequency

def Ebfit(x,a,b):
    Eb_mean = a*(0.0256/kt)                       # Eb at bake temperature
    Eb_sigma = b*Eb_mean
    Foursigma =  4*Eb_sigma
    Eb_a = np.linspace(Eb_mean-Foursigma,Eb_mean+Foursigma,N_Device)
    dEb = Eb_a[1] - Eb_a[0]
    pdfEb_a = spys.norm.pdf(Eb_a,Eb_mean,Eb_sigma)

    ## Retention Time

    DMom = np.zeros(len(x),float)
    tau = (1/f0)*np.exp(Eb_a)
    for bb in range(len(x)):
        DMom[bb]= (1 - 2*(sum(pdfEb_a*(1 - np.exp(np.divide(-x[bb],tau))))*dEb))
    return DMom

a = 30
b = 0.10

params,extras = curve_fit(Ebfit,time,Moment)

x_new = list(range(0,2000,1))
y_new = Ebfit(x_new,params[0],params[1])

plt.plot(time,Moment, 'o', label = 'data points')
plt.plot(x_new,y_new, label = 'fitted curve')
plt.legend()

Le principal problème que je rencontre est que l'ajustement des données à la fonction ne fonctionne pas lorsque j'utilise un grand nombre de points. Dans le code ci-dessus, lorsque j'utilise 4 points (temps et moment), ce code fonctionne correctement.

J'obtiens les valeurs suivantes pour a y b .

array([ 29.11832766, 0.13918353])

Les valeurs attendues pour a sont (23-50) et b est (0.06 - 0.15). Ces valeurs se situent donc dans la fourchette acceptable. Voici le graphique correspondant : Plot 1

Cependant, lorsque j'utilise mes données expérimentales normalisées réelles avec environ 500 points.

EDIT : Ces données :

Données normalisées

https://www.dropbox.com/s/64zke4wckxc1r75/Normalized%20Data.csv?dl=0

Données brutes

https://www.dropbox.com/s/ojgse5ibp59r8nw/Data1.csv?dl=0

J'obtiens les valeurs et le graphique suivants pour a y b qui se situent en dehors de la fourchette acceptable,

array([-13. Plot 2

Je sais que ces valeurs sont erronées et si je devais le faire manuellement (en ajustant lentement les valeurs pour obtenir l'ajustement adéquat), cela donnerait environ a=30.1 y b=0.09 . Et lorsqu'il est tracé, il se présente comme suit : Plot 3

J'ai essayé de modifier les valeurs initiales de l'estimation pour a & b Il y a aussi d'autres ensembles de données expérimentales et d'autres suggestions dans des fils de discussion similaires. Aucune ne semble fonctionner pour moi. Toute aide que vous pourrez m'apporter sera appréciée. Je vous remercie.

. . . .

INFORMATIONS COMPLÉMENTAIRES

Le modèle auquel j'essaie d'adapter les données provient de l'équation suivante : Equation

où Dmom = 1 - 2*Pw

a est la valeur Eb tandis que b est la valeur Sigma où Eb a une plage de valeurs déterminée par la fonction de densité de probabilité et 4 fois les valeurs sigma (c.-à-d. Foursigma). Cette distribution est ensuite additionnée pour être utilisée dans l'équation finale.

2voto

Vlas Sokolov Points 1895

Il semble qu'il faille jouer avec les estimations initiales de a y b après tout. Peut-être que la fonction que vous ajustez ne se comporte pas très bien, ce qui explique pourquoi elle est si encline à échouer pour des suppositions initiales éloignées du minimum global. Ceci étant dit, voici un exemple pratique de la façon d'ajuster vos données :

import pandas as pd
data_df = pd.read_csv('data.csv')
time = data_df['Time since start, Time [s]'].values
moment = data_df['Signal X direction, Moment [emu]'].values

params, extras = curve_fit(Ebfit, time, moment, p0=[40, 0.3])

Donne les valeurs de a y b de :

In [6]: params
Out[6]: array([ 30.47553689,   0.08839412])

Ce qui permet d'obtenir une fonction bien alignée.

x_big = np.linspace(1, 1800, 2000)
y_big = Ebfit(x_big, params[0], params[1])

plt.plot(time, moment, 'o', alpha=0.5, label='all points')
plt.plot(x_big, y_big, label = 'fitted curve')
plt.legend()
plt.show()

fits

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X