200 votes

Comment faire un ajustement de courbe exponentiel et logarithmique en Python ? Je n'ai trouvé que l'ajustement polynomial

J'ai un ensemble de données et je veux comparer quelle ligne la décrit le mieux (polynômes de différents ordres, exponentielle ou logarithmique).

J'utilise Python et Numpy et pour l'ajustement polynomial il y a une fonction polyfit(). Mais je n'ai trouvé aucune fonction similaire pour l'ajustement exponentiel et logarithmique.

Y a-t-il des fonctions disponibles pour cela? Ou comment résoudre autrement ce problème?

4voto

pylang Points 12013

Nous démontrons les fonctionnalités de lmfit tout en résolvant les problèmes.

Données

import lmfit

import numpy as np

import matplotlib.pyplot as plt

%matplotlib inline
np.random.seed(123)

# Fonctions Générales
def func_log(x, a, b, c):
    """Retourne les valeurs d'une fonction logarithmique générale."""
    return a * np.log(b * x) + c

# Données
x_samp = np.linspace(1, 5, 50)
_noise = np.random.normal(size=len(x_samp), scale=0.06)
y_samp = 2.5 * np.exp(1.2 * x_samp) + 0.7 + _noise
y_samp2 = 2.5 * np.log(1.2 * x_samp) + 0.7 + _noise

Code

Approche 1 - Modèle lmfit

Ajustement des données exponentielles

regressor = lmfit.models.ExponentialModel()                # 1    
initial_guess = dict(amplitude=1, decay=-1)                # 2
results = regressor.fit(y_samp, x=x_samp, **initial_guess)
y_fit = results.best_fit    

plt.plot(x_samp, y_samp, "o", label="Données")
plt.plot(x_samp, y_fit, "k--", label="Ajustement")
plt.legend()

description de l'image ici

Approche 2 - Modèle Personnalisé

Ajustement des données logarithmiques

regressor = lmfit.Model(func_log)                          # 1
initial_guess = dict(a=1, b=.1, c=.1)                      # 2
results = regressor.fit(y_samp2, x=x_samp, **initial_guess)
y_fit = results.best_fit

plt.plot(x_samp, y_samp2, "o", label="Données")
plt.plot(x_samp, y_fit, "k--", label="Ajustement")
plt.legend()

description de l'image ici


Détails

  1. Choisissez une classe de régression
  2. Fournissez des suppositions initiales nommées qui respectent le domaine de la fonction

Vous pouvez déterminer les paramètres déduits à partir de l'objet de régression. Exemple:

regressor.param_names
# ['decay', 'amplitude']

Pour faire des prédictions, utilisez la méthode ModelResult.eval().

model = results.eval
y_pred = model(x=np.array([1.5]))

Remarque : le ExponentialModel() suit une fonction de décroissance exponentielle, qui accepte deux paramètres, dont l'un est négatif.

description de l'image ici

Voir aussi ExponentialGaussianModel(), qui accepte plus de paramètres.

Installez la bibliothèque via > pip install lmfit.

2voto

Ben Points 405

Wolfram a une solution de forme fermée pour adapter une exponentielle. Ils ont également des solutions similaires pour adapter un logarithme et une loi de puissance.

J'ai trouvé que cela fonctionne mieux que curve_fit de scipy. Surtout lorsque vous n'avez pas de données "proches de zéro". Voici un exemple:

import numpy as np
import matplotlib.pyplot as plt

# Adapter la fonction y = A * exp(B * x) aux données
# retourne (A, B)
# De: https://mathworld.wolfram.com/LeastSquaresFittingExponential.html
def fit_exp(xs, ys):
    S_x2_y = 0.0
    S_y_lny = 0.0
    S_x_y = 0.0
    S_x_y_lny = 0.0
    S_y = 0.0
    for (x,y) in zip(xs, ys):
        S_x2_y += x * x * y
        S_y_lny += y * np.log(y)
        S_x_y += x * y
        S_x_y_lny += x * y * np.log(y)
        S_y += y
    #end
    a = (S_x2_y * S_y_lny - S_x_y * S_x_y_lny) / (S_y * S_x2_y - S_x_y * S_x_y)
    b = (S_y * S_x_y_lny - S_x_y * S_y_lny) / (S_y * S_x2_y - S_x_y * S_x_y)
    return (np.exp(a), b)

xs = [33, 34, 35, 36, 37, 38, 39, 40, 41, 42]
ys = [3187, 3545, 4045, 4447, 4872, 5660, 5983, 6254, 6681, 7206]

(A, B) = fit_exp(xs, ys)

plt.figure()
plt.plot(xs, ys, 'o-', label='Données brutes')
plt.plot(xs, [A * np.exp(B *x) for x in xs], 'o-', label='Ajustement')

plt.title('Test d\'ajustement exponentiel')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend(loc='best')
plt.tight_layout()
plt.show()

description de l'image

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