Saltar al contenido

funciones logit y logit inversa para valores extremos

No busques más por todo internet ya que has llegado al espacio indicado, contamos con la solución que deseas sin problemas.

Solución:

Cualquiera de los usos

1. El paquete bigfloat con soportes precisión arbitraria flotante operaciones puntuales.

2. El SimPy simbólico paquete matematico Daré ejemplos de ambos:

Primero, gran flotador:

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

Aquí hay un ejemplo simple:

from bigfloat import *
def logit(p):
    with precision(100000):
        return log(p)- log(1 -BigFloat(p))

def inv_logit(p):
    with precision(100000):
        return exp(p) / (1 + exp(p))

int(round(logit(inv_logit(12422.0))))
# gives 12422
int(round(logit(inv_logit(-12422.0))))
# gives -12422

Esto es realmente lento. Es posible que desee considerar la reestructuración de su problema y hacer algunas partes analíticamente. Casos como estos son raros en problemas reales. Tengo curiosidad sobre en qué tipo de problema está trabajando.

Ejemplo de instalación:

wget http://pypi.python.org/packages/source/b/bigfloat/bigfloat-0.3.0a2.tar.gz
tar xvzf bigfloat-0.3.0a2.tar.gz 
cd bigfloat-0.3.0a2
as root:
python setup.py install

Sobre la razón por la que sus funciones funcionaban mejor con valores negativos. Considerar:

>>> float(inv_logit(-15))
3.059022269256247e-07

>>> float(inv_logit(15))
0.9999996940977731

En el primer caso, los números de coma flotante representan fácilmente este valor. El punto decimal se mueve para que no sea necesario almacenar los ceros iniciales: 0.0000… En el segundo caso, todos los 0.999 iniciales deben almacenarse, por lo que necesita toda esa precisión adicional para obtener un resultado exacto cuando luego haga 1-p en logit().

Aquí está la forma matemática simbólica (¡significativamente más rápido!):

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()

Sympy se encuentra aquí http://docs.sympy.org/. En ubuntu se encuentra a través de synaptic.

Hay una forma de implementar las funciones para que sean estables en un amplio rango de valores pero implica una distinción de casos dependiendo del argumento.

Tomemos por ejemplo la función inv_logit. Su fórmula “np.exp(p) / (1 + np.exp(p))” es correcta pero se desbordará para grandes p. Si divides numerador y denominador por np.exp(p) obtienes la expresión equivalente

1. / (1. + np.exp(-p))

La diferencia es que este no se desbordará por una gran p positiva. Sin embargo, se desbordará para grandes valores negativos de p. Por lo tanto, una implementación estable podría ser la siguiente:

def inv_logit(p):
    if p > 0:
        return 1. / (1. + np.exp(-p))
    elif p <= 0:
        np.exp(p) / (1 + np.exp(p))
    else:
        raise ValueError

Esta es la estrategia utilizada en la biblioteca LIBLINEAR (y posiblemente en otras).

No se te olvide dar recomendación a este tutorial si si solucionó tu problema.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *