logit和反逻辑函数的极值 [英] logit and inverse logit functions for extreme values

查看:274
本文介绍了logit和反逻辑函数的极值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要logit和反逻辑函数,使得 logit(inv_logit(n))== n 。我使用numpy,这是我有:

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

这里是值:

  print logit(inv_logit(2))
2.0

print logit(inv_logit(10))
10.0

print logit(inv_logit(20))
20.000000018 #well,close close

print logit(inv_logit(50))
警告:日志
inf

现在让我们测试负数

  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))
警告:在log
-inf

中遇到的零除以所以我的问题是:什么是道具呃实现这些函数的方法,以便任何 n 的要求 logit(inv_logit(n))== n >在尽可能宽的范围内(至少[-1e4; 1e4)?

还有(我确定这是连接到第一个),为什么我的函数更稳定的负值,与积极的?

解决方案

使用


支持任意精确浮点点操作的bigfloat包。


2。
SymPy 符号数学包。我会举两个例子:



首先,bigfloat:

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



这里有一个简单的例如:

  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( (logit(inv_logit(12422.0))))
#给出12422
int(round(logit(inv_logit (-12422.0))))
#给出-12422

这真的很慢。您可能要考虑重组您的问题,并分析一些部分。像这样的情况在实际问题中很少见 - 我很好奇你正在处理什么样的问题。



安装示例:

  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
作为root:
python setup.py install

关于你的函数用负值更好的原因。考虑:

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

>>> float(inv_logit(15))
0.9999996940977731

在第一种情况下,浮点数表示这个价值很容易。移动小数点以便前导零:0.0000 ...不需要存储。在第二种情况下,所有前导0.999都需要存储,所以在logit()中稍后做1-p时,需要所有额外的精度才能得到确切的结果。



以下是符号数学方式(明显更快!):

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

x =符号('x')
expr = logit(inv_logit(x))
#expr is现在:
#-log(1 -exp(x)/(1 + exp(x)))+ log(exp(x)/(1 + exp(x)))
# :(还有很多其他的方法可以做到这一点,阅读文档)
#你可能想要扩展(某种合适的类型)。
expr = cancel(powsimp(expr))。expand()
#现在是'x'

#只需计算如下所示的任何表达式:
result = expr.subs(x,123.231)

#结果现在是一个等式:123.231
#获得浮点数:
result.evalf()
code>

Sympy在这里找到 http ://docs.sympy.org/ 。在ubuntu中,它是通过突触发现的。


I need logit and inverse logit functions so that logit(inv_logit(n)) == n. I use numpy and here is what I have:

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

And here are the values:

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 

Now let's test negative numbers

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 

So my questions are: what is the proper way to implement these functions so that the requirement logit(inv_logit(n)) == n will hold for any n in as wide a range as possible (at least [-1e4; 1e4)?

And also (and I'm sure this is connected to the first one), why are my function more stable with negative values, compared to the positive ones?

解决方案

Either use

1. The bigfloat package with supports arbitrary precision floating point operations.

2. The SymPy symbolic math package. I'll give examples of both:

First, bigfloat:

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

Here's a simple example:

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

This is really slow. You may want to consider restructuring your problem and do some parts analytically. Cases like these are rare in real problems - I'm curious about what kind of problem you are working on.

Example installation:

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

About the reason your functions wore better with negative values. Consider:

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

>>> float(inv_logit(15))
0.9999996940977731

In the first case floating point numbers represent this value easily. The decimal point is moved so that the leading zeroes: 0.0000... does not need to be stored. In the second case all the leading 0.999 needs to be stored, so you need all that extra precision to get an exact result when later doing 1-p in logit().

Here's the symbolic math way (significantly faster!):

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 is found here http://docs.sympy.org/. In ubuntu it's found via synaptic.

这篇关于logit和反逻辑函数的极值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆