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.
y
es sich um kleine Punkte handelt, werden künstlich übergewichtet. Es ist besser, die Funktion (linear, nicht die Protokolltransformation) zu definieren und einen Kurvenmonteur oder Minimierer zu verwenden.Sie können auch einen Datensatz an eine beliebige Funktion anpassen, die Sie verwenden
curve_fit
möchtenscipy.optimize
. Zum Beispiel, wenn Sie eine Exponentialfunktion anpassen möchten (aus der Dokumentation ):Und wenn Sie dann zeichnen möchten, können Sie Folgendes tun:
(Hinweis: Die
*
vor ,popt
wenn Sie die Begriffe in die expandieren aus plota
,b
und ,c
Dasfunc
. Erwartet)quelle
a
,b
undc
?Ich hatte einige Probleme damit, also lass mich sehr explizit sein, damit Noobs wie ich verstehen können.
Nehmen wir an, wir haben eine Datendatei oder ähnliches
Das Ergebnis ist: a = 0,849195983017, b = -1,18101681765, c = 2,24061176543, d = 0,816643894816
quelle
y = [np.exp(i) for i in x]
ist sehr langsam; Ein Grund, warum Numpy erstellt wurde, war, dass Sie schreiben konnteny=np.exp(x)
. Mit diesem Ersatz können Sie auch Ihren brutalen Kraftabschnitt loswerden. In Ipython gibt es die%timeit
Magie, aus derIn [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)
sollte es Ihnen ermöglichen, das langsame Listenverständnis loszuwerden.Nun, ich denke, Sie können immer verwenden:
Die Antwort von IanVS leicht modifizieren :
Dies führt zu der folgenden Grafik:
quelle
Hier ist eine Linearisierungsoption für einfache Daten, die Tools von scikit learn verwendet .
Gegeben
Code
Exponentialdaten anpassen
Protokolldaten anpassen
Einzelheiten
Allgemeine Schritte
x
,y
oder beides)np.exp()
) "umkehren" und an die Originaldaten anpassenUnter der Annahme, dass unsere Daten einem exponentiellen Trend folgen, kann eine allgemeine Gleichung + sein:
Wir können die letztere Gleichung (z. B. y = Achsenabschnitt + Steigung * x) linearisieren, indem wir das Protokoll nehmen :
Mit einer linearisierten Gleichung ++ und den Regressionsparametern könnten wir berechnen:
A
via intercept (ln(A)
)B
über Steigung (B
)Zusammenfassung der Linearisierungstechniken
+ Hinweis: Die Linearisierung von Exponentialfunktionen funktioniert am besten, wenn das Rauschen klein und C = 0 ist. Mit Vorsicht verwenden.
++ Hinweis: Während das Ändern von x-Daten zur Linearisierung exponentieller Daten beiträgt , hilft das Ändern von y-Daten zur Linearisierung von Protokolldaten .
quelle
Wir demonstrieren Merkmale bei der
lmfit
Lösung beider Probleme.Gegeben
Code
Ansatz 1 -
lmfit
ModellExponentialdaten anpassen
Ansatz 2 - Benutzerdefiniertes Modell
Protokolldaten anpassen
Einzelheiten
Sie können die abgeleiteten Parameter aus dem Regressorobjekt ermitteln. Beispiel:
Hinweis: Es
ExponentialModel()
folgt eine Abklingfunktion , die zwei Parameter akzeptiert, von denen einer negativ ist.Siehe auch
ExponentialGaussianModel()
, das weitere Parameter akzeptiert .Installieren Sie die Bibliothek über
> pip install lmfit
.quelle
Wolfram hat eine geschlossene Lösung zum Anpassen eines Exponentials . Sie haben auch ähnliche Lösungen für die Anpassung eines Logarithmus- und Potenzgesetzes .
Ich fand, dass dies besser funktioniert als Scipys Curve_Fit. Hier ist ein Beispiel:
quelle