Pour ajuster y = A + B log x, ajustez simplement y par rapport à (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. Donc ajustez (log y) par rapport à x.
Remarquez que l'ajustement de (log y) comme s'il était linéaire accentuera les petites valeurs de y, provoquant de fortes déviations pour de grandes valeurs de y. Cela est dû au fait que polyfit
(régression linéaire) fonctionne en minimisant ∑<em>i</em> (ΔY)2 = ∑<em>i</em> (Yi − Ŷ<em>i</em>)2. Lorsque Y<em>i</em> = log y<em>i</em>, les résidus ΔY<em>i</em> = Δ(log y<em>i</em>) ≈ Δy<em>i</em> / |y<em>i</em>|. Ainsi, même si polyfit
prend une très mauvaise décision pour de grandes valeurs de y, le facteur "divisé par |y|" compensera, faisant en sorte que 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'argument mot-clé w
.
>>> 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)
# (^ biaisé vers les petites valeurs)
>>> 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)
# (^ moins biaisé)
Notez qu'Excel, LibreOffice et la plupart des calculatrices scientifiques utilisent généralement la formule non pondérée (biaisée) pour la régression exponentielle / les lignes de tendance. Si vous voulez que vos résultats soient compatibles avec ces plateformes, n'incluez pas les poids même s'ils offrent de meilleurs résultats.
Maintenant, si vous pouvez utiliser scipy, vous pourriez utiliser scipy.optimize.curve_fit
pour ajuster 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 directement Δ(log y). Mais nous devons fournir une estimation initiale pour que curve_fit
puisse atteindre le minimum local désiré.
>>> 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]]))
# oups, complètement faux.
>>> 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). bien mieux.