Zum Anpassen von y = A + B log x passen Sie einfach y gegen (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
Nehmen Sie für die Anpassung von y = Ae Bx den Logarithmus beider Seiten und geben Sie log y = log A + Bx an . Passen Sie also (log y ) gegen x an .
Beachten Sie, dass die Anpassung (log y ) als linear kleine Werte von y hervorhebt , was zu einer großen Abweichung für großes y führt . Dies liegt daran, dass polyfit
(lineare Regression) durch Minimieren von ∑ i (Δ Y ) 2 = ∑ i ( Y i - Ŷ i ) 2 funktioniert . Wenn Y i = log y i ist , sind die Reste Δ Y i = Δ (log y i ) ≈ Δ y i / | y i |. Also auch wennpolyfit
trifft eine sehr schlechte Entscheidung für großes y , das "dividieren durch | y |" Faktor wird dies kompensieren und polyfit
kleine Werte begünstigen.
Dies könnte gemildert werden, indem jedem Eintrag ein "Gewicht" proportional zu y gegeben wird . polyfit
unterstützt gewichtete kleinste Quadrate über das w
Schlüsselwortargument.
>>> 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)
Beachten Sie, dass Excel, LibreOffice und die meisten wissenschaftlichen Taschenrechner normalerweise die ungewichtete (voreingenommene) Formel für die exponentiellen Regressions- / Trendlinien verwenden. Wenn Sie möchten, dass Ihre Ergebnisse mit diesen Plattformen kompatibel sind, geben Sie die Gewichte nicht an, auch wenn dadurch bessere Ergebnisse erzielt werden.
Wenn Sie jetzt scipy verwenden können, können Sie scipy.optimize.curve_fit
jedes Modell ohne Transformationen anpassen .
Für y = A + B log x ist das Ergebnis dasselbe wie für die Transformationsmethode:
>>> 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)
Für y = Ae Bx können wir jedoch eine bessere Anpassung erhalten, da es Δ (log y ) direkt berechnet . Wir müssen jedoch eine Initialisierungsschätzung abgeben, damit curve_fit
das gewünschte lokale Minimum erreicht werden kann.
>>> 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.