Pour ajuster y = A + B log x , ajustez simplement y contre (log x ).
>>> x = numpy.array([1, 7, 20, 50, 79])
>>> y = numpy.array([10, 19, 30, 35, 51])
>>> numpy.polyfit(numpy.log(x), y, 1)
array([ 8.46295607, 6.61867463])
# y ≈ 8.46 log(x) + 6.62
Pour ajuster y = Ae Bx , prendre le logarithme des deux côtés donne log y = log A + Bx . Alors ajustez (log y ) contre x .
Notez que l'ajustement (log y ) comme s'il était linéaire accentuera les petites valeurs de y , provoquant un grand écart pour un y grand . En effet, la polyfit
(régression linéaire) fonctionne en minimisant ∑ i (Δ Y ) 2 = ∑ i ( Y i - Ŷ i ) 2 . Lorsque Y i = log y i , les résidus Δ Y i = Δ (log y i ) ≈ Δ y i / | y i |. Donc même sipolyfit
prend une très mauvaise décision pour un grand y , le "divide-by- | y |" facteur compensera cela, ce qui polyfit
favorise les petites valeurs.
Cela pourrait être atténué en donnant à chaque entrée un "poids" proportionnel à y . polyfit
prend en charge les moindres carrés pondérés via l' w
argument mot - clé.
>>> x = numpy.array([10, 19, 30, 35, 51])
>>> y = numpy.array([1, 7, 20, 50, 79])
>>> numpy.polyfit(x, numpy.log(y), 1)
array([ 0.10502711, -0.40116352])
# y ≈ exp(-0.401) * exp(0.105 * x) = 0.670 * exp(0.105 * x)
# (^ biased towards small values)
>>> numpy.polyfit(x, numpy.log(y), 1, w=numpy.sqrt(y))
array([ 0.06009446, 1.41648096])
# y ≈ exp(1.42) * exp(0.0601 * x) = 4.12 * exp(0.0601 * x)
# (^ not so biased)
Notez qu'Excel, LibreOffice et la plupart des calculatrices scientifiques utilisent généralement la formule non pondérée (biaisée) pour les lignes de régression / tendance exponentielles. Si vous souhaitez que vos résultats soient compatibles avec ces plates-formes, n'incluez pas les poids même si cela donne de meilleurs résultats.
Maintenant, si vous pouvez utiliser scipy, vous pouvez utiliser scipy.optimize.curve_fit
pour adapter n'importe quel modèle sans transformations.
Pour y = A + B log x, le résultat est le même que la méthode de transformation:
>>> x = numpy.array([1, 7, 20, 50, 79])
>>> y = numpy.array([10, 19, 30, 35, 51])
>>> scipy.optimize.curve_fit(lambda t,a,b: a+b*numpy.log(t), x, y)
(array([ 6.61867467, 8.46295606]),
array([[ 28.15948002, -7.89609542],
[ -7.89609542, 2.9857172 ]]))
# y ≈ 6.62 + 8.46 log(x)
Pour y = Ae Bx , cependant, nous pouvons obtenir un meilleur ajustement car il calcule Δ (log y ) directement. Mais nous devons fournir une estimation d'initialisation pour curve_fit
pouvoir atteindre le minimum local souhaité.
>>> x = numpy.array([10, 19, 30, 35, 51])
>>> y = numpy.array([1, 7, 20, 50, 79])
>>> scipy.optimize.curve_fit(lambda t,a,b: a*numpy.exp(b*t), x, y)
(array([ 5.60728326e-21, 9.99993501e-01]),
array([[ 4.14809412e-27, -1.45078961e-08],
[ -1.45078961e-08, 5.07411462e+10]]))
# oops, definitely wrong.
>>> scipy.optimize.curve_fit(lambda t,a,b: a*numpy.exp(b*t), x, y, p0=(4, 0.1))
(array([ 4.88003249, 0.05531256]),
array([[ 1.01261314e+01, -4.31940132e-02],
[ -4.31940132e-02, 1.91188656e-04]]))
# y ≈ 4.88 exp(0.0553 x). much better.
y
sont petites seront artificiellement surpondérées. Il est préférable de définir la fonction (linéaire, pas la transformation logarithmique) et d'utiliser un ajusteur de courbe ou un minimiseur.Vous pouvez également adapter un ensemble de données que vous fonctionne comme l' utilisation
curve_fit
descipy.optimize
. Par exemple si vous souhaitez adapter une fonction exponentielle (à partir de la documentation ):Et puis si vous voulez tracer, vous pouvez faire:
(Note: le
*
devantpopt
lorsque vous tracer étendra les termes dans lea
,b
etc
quefunc
. ATTEND)la source
a
,b
etc
?J'avais des problèmes avec cela, alors laissez-moi être très explicite pour que les noobs comme moi puissent comprendre.
Disons que nous avons un fichier de données ou quelque chose comme ça
le résultat est: a = 0,849195983017, b = -1,18101681765, c = 2,24061176543, d = 0,816643894816
la source
y = [np.exp(i) for i in x]
Est très lent; l'une des raisons pour lesquelles numpy a été créé était pour que vous puissiez écrirey=np.exp(x)
. De plus, avec ce remplacement, vous pouvez vous débarrasser de votre section de force brutale. En ipython, il y a la%timeit
magie à partir de laquelleIn [27]: %timeit ylist=[exp(i) for i in x] 10000 loops, best of 3: 172 us per loop In [28]: %timeit yarr=exp(x) 100000 loops, best of 3: 2.85 us per loop
x = np.array(x, dtype=float)
devrait vous permettre de vous débarrasser de la compréhension lente des listes.Eh bien, je suppose que vous pouvez toujours utiliser:
Modification légèrement de la réponse d'IanVS :
Cela donne le graphique suivant:
la source
Voici une option de linéarisation sur des données simples qui utilise des outils de scikit learn .
Donné
Code
Ajuster les données exponentielles
Ajuster les données du journal
Détails
Étapes générales
x
,y
ou les deux)np.exp()
) et ajustez les données d'origineEn supposant que nos données suivent une tendance exponentielle, une équation générale + peut être:
On peut linéariser cette dernière équation (par exemple y = intersection + pente * x) en prenant le log :
Étant donné une équation linéarisée ++ et les paramètres de régression, nous pourrions calculer:
A
via interception (ln(A)
)B
par pente (B
)Résumé des techniques de linéarisation
+ Remarque: la linéarisation des fonctions exponentielles fonctionne mieux lorsque le bruit est petit et C = 0. Utiliser avec précaution.
++ Remarque: alors que la modification des données x aide à linéariser les données exponentielles , la modification des données y aide à linéariser les données du journal .
la source
Nous démontrons les fonctionnalités de
lmfit
tout en résolvant les deux problèmes.Donné
Code
Approche 1 -
lmfit
ModèleAjuster les données exponentielles
Approche 2 - Modèle personnalisé
Ajuster les données du journal
Détails
Vous pouvez déterminer les paramètres déduits à partir de l'objet régresseur. Exemple:
Remarque: le
ExponentialModel()
suit une fonction de décroissance , qui accepte deux paramètres, dont l'un est négatif.Voir aussi
ExponentialGaussianModel()
, qui accepte plus de paramètres .Installez la bibliothèque via
> pip install lmfit
.la source
Wolfram a une solution de forme fermée pour ajuster une exponentielle . Ils ont également des solutions similaires pour ajuster une loi logarithmique et de puissance .
J'ai trouvé que cela fonctionnait mieux que le curve_fit de scipy. Voici un exemple:
la source