logit-und inverse logit-Funktionen für extreme Werte
Brauche ich logit-und inverse logit-Funktionen, so dass logit(inv_logit(n)) == n
. Ich benutze numpy und hier ist was ich habe:
import numpy as np
def logit(p):
return np.log(p) - np.log(1 - p)
def inv_logit(p):
return np.exp(p) / (1 + np.exp(p))
Und hier sind die Werte:
print logit(inv_logit(2))
2.0
print logit(inv_logit(10))
10.0
print logit(inv_logit(20))
20.000000018 #well, pretty close
print logit(inv_logit(50))
Warning: divide by zero encountered in log
inf
Nun testen wir, negative zahlen
print logit(inv_logit(-10))
-10.0
print logit(inv_logit(-20))
-20.0
print logit(inv_logit(-200))
-200.0
print logit(inv_logit(-500))
-500.0
print logit(inv_logit(-2000))
Warning: divide by zero encountered in log
-inf
Also meine Fragen sind: was ist der richtige Weg, um diese Funktionen zu implementieren, so dass die Anforderung logit(inv_logit(n)) == n
halten für jeden n
so weit reichen wie möglich (mindestens [-1e4; 1e4)?
Und auch (und ich bin sicher, dies ist mit dem ersten verbunden), warum sind meine Funktion, mehr stabil mit negativen Werten im Vergleich zu den positiven?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Entweder
1.
Die bigfloat-Paket mit unterstützt beliebiger Genauigkeit floating point-Operationen.
2.
Die SymPy symbolischen math-Paket. Ich gebe Beispiele für beide:
Erste, bigfloat:
http://packages.python.org/bigfloat/
Hier ein einfaches Beispiel:
Ist es wirklich langsam. Vielleicht möchten Sie erwägen Umstrukturierung dein problem und einige Teile analytisch. Fälle wie diese sind selten in echte Probleme - ich bin neugierig, welche Art von problem Sie arbeiten.
Beispiel-installation:
Über den Grund Ihrer Funktionen waren besser mit negativen Werten. Bedenken Sie:
Im ersten Fall Gleitkommazahlen repräsentieren diesen Wert leicht. Der Dezimalpunkt wird so verschoben, dass die führenden Nullen: 0.0000... muss nicht gespeichert werden. Im zweiten Fall werden alle führenden 0.999, die gespeichert werden muss, so müssen Sie alle, dass zusätzliche Präzision, um eine genaue Ergebnis, als später tun, 1-p logit().
Hier ist die symbolic math Weg (deutlich schneller!):
Sympy ist hier zu finden http://docs.sympy.org/. In ubuntu ist es über synaptic.
Es ist ein Weg, um die Funktionen implementiert, so dass Sie stabil sind, in eine Vielzahl von Werten, sondern es sich um eine Unterscheidung der Fälle, je nach argument.
Nehmen Sie zum Beispiel die inv_logit Funktion. Die Formel "np.exp(p) /(1 + np.exp(p))" ist korrekt, aber ein überlauf für große p. Teilt man Zähler und Nenner durch die np.exp(p) Sie erhalten die entsprechende Ausdruck
Dem Unterschied, dass diese nicht überlaufen-für die große positive p. Überlauf wird jedoch für große negative Werte von p. Also, eine stabile Implementierung könnte wie folgt Aussehen:
Dies ist die Strategie, in der Bibliothek LIBLINEAR (und eventuell andere).
Läufst du gegen die Präzision Grenzwerte für IEEE 754 double-precision-float. Benötigen Sie eine höhere Genauigkeit zahlen und Operationen-wenn Sie möchten, eine größere Reichweite und eine genauere domain.
Meine Variante von Fabian Pedregosa ' s Antwort:
def stable_inv_logit(x):
return 0.5*(1. + np.sign(x)*(2./(1. + np.exp(-np.abs(x))) - 1.))