Sunday, February 5, 2012

Algunos tips para no olvidar

Ultimamente he estado ocupando muchos tips de PYTHON que son tan invaluables que los necesito dejar guardados por acá.

Algo útil para obtener likelihoods en MLE, MCMC, etc.

El primero que ocupé recientemente es la función slogdet de NUMPY. El contexto del problema es que tengo una matriz más o menos grande (100x100) a la cual le necesito sacar el logaritmo del valor absoluto del determinante en varias iteraciones (~100.000) donde sus términos pueden ser muy pequeños (<<1) o muy cercanos a 1.

El problema es que cuando se hacen pequeños, el determinante se hace muy, muy pequeño (imaginen una matriz diagonal con términos << 1, digamos, 0.0001, lo que resultaría en un determinante igual a (0.0001)^100=10^-400). El problema es que el determinante es tan pequeño que se acaba la capacidad de cualquier número que se pueda guardar, el resultado que se lanza es 0.0 y el logaritmo de eso no existe, por lo que el código (obviamente) se cae. Buscando de esas descomposiciones que a uno le enseñan en Álgebra Lineal, encontré este código que tiene NUMPY el cual se basa en una descomposición LU para obtener el resultado: es cosa de aplicar slogdet(matriz) y se nos devuelven dos números: el primero es el signo del determinante (irrelevante para mi caso, pues quiero el logaritmo del valor absoluto) y el logaritmo del valor absoluto del determinante (¡lo que yo necesito!). Genial...¿no?

Un comando útil para definir variables y otras cosas en PYTHON.

El siguiente es un comando de PYTHON que para mi no había existido hasta hace algún tiempo: el comando exec. Supongamos que queremos definir una variable X en PYTHON, que sea igual a 1234. Hay dos maneras de hacerlo en PYTHON. Una es lo usual, i.e.,

X = 1234

Otra manera es haciendo

exec 'X=1234'


Lo que hace exec es ejecutar un comando, el cual uno pasa como un string. Quizá esto no sonará muy útil, pero si que lo es. Por ejemplo, supongamos que queremos definir 30 variables, a1, a2, a3,..., a30. A mano, esto es una lata, pero con exec es lo más fácil del mundo

for i in range(30):
exec 'a'+str(i+1)+'=1234'

(Recordemos que str(entero) transforma un entero en un string).

WARNING: A pesar de la utilidad de este comando, algunos ponen ojo en que es más o menos peligroso: si hacemos algo inusual, exec nos puede jugar en contra, asi que usenlo sólo cuando sepan exactamente lo que estan haciendo :-).