9
votes

Logit et inverse logit fonctions pour des valeurs extrêmes

J'ai besoin de fonctions de logit et inverse logit de sorte que logit (inv_logit (n)) == n . J'utilise numpy et voici ce que j'ai: xxx

et voici les valeurs suivantes: xxx

testons les nombres négatifs xxx

Donc, mes questions sont: Quelle est la manière appropriée de mettre en œuvre ces fonctions afin que l'exigence logit (inv_logit (n)) == n tout n dans une plage aussi large que possible (au moins [-1e4; 1e4)?

et aussi (et je suis sûr que cela est connecté au premier), Pourquoi ma fonction est-elle plus stable avec des valeurs négatives, comparées aux positives?


0 commentaires

5 Réponses :


2
votes

Vous courez contre les limites de précision pour un flotteur à double précision IEEE 754. Vous devrez utiliser des numéros et des opérations plus haut de précision si vous souhaitez une gamme plus grande et un domaine plus précis.

>>> 1 + np.exp(-37)
1.0
>>> 1 + decimal.Decimal(-37).exp()
Decimal('1.000000000000000085330476257')


0 commentaires

12
votes

Utiliser

1. Le paquet BigFloat avec des supports Explication de précision arbitraire flottante forte> points de points. P>

2. Le symbolique Symbolic Symbolic Strong> Math Math. Je vais donner des exemples des deux: p>

premier, BigFloat: P>

http://packages.python.org/bigfloat/ p>

Voici un exemple simple: p> xxx pré>

C'est vraiment lent. Vous voudrez peut-être envisager de restructurer votre problème et de faire des pièces analytiquement. Des cas comme ceux-ci sont rares dans de vrais problèmes - je suis curieux de savoir quel type de problème vous travaillez. P>

Exemple Installation: P>

from sympy import *
def inv_logit(p):
    return exp(p) / (1 + exp(p))
def logit(p):
    return log(p)- log(1 -p)

x=Symbol('x')
expr=logit(inv_logit(x))
# expr is now:
# -log(1 - exp(x)/(1 + exp(x))) + log(exp(x)/(1 + exp(x)))
# rewrite it: (there are many other ways to do this. read the doc)
# you may want to make an expansion (of some suitable kind) instead.
expr=cancel(powsimp(expr)).expand()
# it is now 'x'

# just evaluate any expression like this:    
result=expr.subs(x,123.231)

# result is now an equation containing: 123.231
# to get the float: 
result.evalf()


0 commentaires

8
votes

Il existe un moyen de mettre en œuvre les fonctions afin qu'elles soient stables dans un large éventail de valeurs, mais cela implique une distinction de cas en fonction de l'argument.

prendre par exemple la fonction inv_logit. Votre formule "np.exp (p) / (1 + np.exp (p))" est correcte mais débordera pour Big P. Si vous divisez le numérateur et le dénominateur de NP.EXP (P), vous obtenez l'expression équivalente xxx

la différence étant que celle-ci ne déborde pas de grand positif p. Il déborde toutefois de grosses valeurs négatives de p. Ainsi, une implémentation stable pourrait être la suivante: xxx

Il s'agit de la stratégie utilisée dans la bibliothèque liblinear (et éventuellement d'autres).


0 commentaires

0
votes

Ma variante de la réponse de Fabian Pedregosa: def stables_inv_logit (x): Retour 0.5 * (1. + np.sign (X) * (2.//(1. + np.exp (-np.abs (x))) - 1.)))


0 commentaires

2
votes

De nos jours, Scipire a Logit et Office (logit inverse), par exemple xxx


0 commentaires