Todas las entradas de: rocreguant

Cuándo abandonar

Hace ya unos días @Ana me pasó el link de un podcast de Tim Ferris para que lo escuchara. Este podcast distintas personas famosas entre las cuales hay Seth Goldin y James Altutcher exponen las distintas razones por las cuales persistir o abandonar una meta. El podcast consiste en mensajes grabados exponiendo las opiniones de las distintas personalidades uno detrás de otro pero sin tener el formato de entrevista o mesa redonda donde los participantes interactúan. Dicho podcast me ha parecido extremadamente interesante. Lo he escuchado un par de veces tomando apuntes la segunda vez. Como quería poder revisar las ideas más adelante he escrito este post para poder revisar los conceptos mas adelante pero a la vez compartirlas con el mundo. ¡Ahora sin más dilaciones vamos al curro!

El problema principal es la diferenciación entre una mala idea vs una idea que no ha funcionado aún. Quiero remarcar la palabra aún ya que es de vital importancia estresar la diferencia entre un proyecto que no va a funcionar de uno que si. Un proyecto que *aún* no ha funcionado es una meta que con persistencia conseguiremos alcanzar atravesando el abismo (o dip en ingles). Por el contrario si un proyecto no funciona (sin el aun) nunca lo hará. La clave esta en saber diferenciar entre el proyecto que nunca va a funcionar de uno que si lo hará dada suficiente perseverancia.

Una de las primeras cosas que tienes que tener en cuenta es evitar la falacia del “coste hundido”. El coste hundido son un tipo de costes (ya sean económicos o emocionales) que ocurrieron en el pasado y que no se pueden recuperar en el tiempo presente. El coste hundido a menudo nos causa “dolor” al abandonar un proyecto después de haber invertido tanto tiempo y esfuerzo. Pese a todo el cariño y dedicación invertidos en un proyecto, abandonar puede ser la opción mas sensata. Cuanto antes dejes el proyecto fallido menos recursos invertiremos fútilmente, menos costoso a nivel personal te va a resultar y antes podrás comenzar de nuevo. No tengas miedo de abandonar proyectos que consideres fallidos pero a su vez no abandones proyectos por capricho. Recuerda que a menudo el camino hacia el objetivo es difícil y contiene abismos que superar. Si abandonamos metas sin llegar a superar el abismo nunca llegaremos a la meta ni obtendremos los objetivos que nos propongamos.

El abismo es el motivo que hace el proyecto digno de ser perseguido. Si no hay abismo cualquiera puede conseguir la meta restando valor al resultado final. Cuando todos pueden llegar al mismo objetivo, llegar a la meta se convierte en algo trivial ¿dónde queda luego la satisfacción de un trabajo bien hecho y una recompensa merecida? El abismo es el mecanismo para separar los que deseen un objetivo con suficiente fuerza de los que no tienen la persistencia para endurar. En la universidad típicamente el primer año es el que contiene las asignaturas más odiadas por los alumnos. Pero cualquier estudiante que desee conseguir la carrera se le precisan dichas asignaturas. Cualquier persona que no desee con suficiente fuerza sacarse la carrera abandonara y escogerá otra facultad para terminar otra carrera. Pero si por lo contrario estás dispuesto a pelearte con asignaturas que son difíciles, al cabo de unos años en la ceremonia de graduación estarás eufórico por haber conseguido obtener el titulo. En ese momento ya prácticamente no te acordaras de esas asignaturas de primero que todos sufristeis y que a nadie le gustaban. Pero esas asignaturas que tu superaste sirvieron de barrera para las personas que no lo tenían muy claro.

Aunque te parezca que estas solo peleando contra los elementos en un lugar inhóspito, difícilmente serás el primero que pase por el abismo. Casi siempre habrá alguien que ya haya pasado por lo que tú estas pasando o por lo menos por algo muy similar. Es extremadamente difícil ir por un sendero virgen en el que nadie más se haya aventurado. No es imposible, pero difícilmente serás el primero. Si es así, si realmente eres el primero en ir andando por el camino, ten cuidado quizás estés fumando tu propio crack…

Tienes que ser sincero contigo mismo. Des del principio poner unas métricas y objetivos bien definidos y revisarlos durante el transcurso del proyecto. Unas métricas y objetivos bien definidos nos ayudaran a saber si seguimos en camino, nos hemos desviado o debemos abandonar. A veces también puede ser que queramos evaluar y reconsiderar si las métricas son válidas o los objetivos siguen estando el día. Pero con cada revisión de métricas tienes que ser cuidadoso ya que puedes caer en la trampa de fumar tu propio crack.

Para saber si estas avanzando o estas atrapado en un callejón sin salida pregúntate si estas sacando algo bueno del trayecto. Si estas obteniendo “activos” probablemente estés avanzando hacia tu meta aunque no lo parezca. Aunque sean pasos pequeños al final vas a llegar a la meta. Obteniendo más clientes, experiencia o conocimiento, y generando posesiones o elementos de valor son pequeños pasos que nos acercan a la meta. SI estas obteniendo activos y persistes al final tendrás tu recompensa. Solo es cuestión de tiempo y esfuerzo hasta llegar a la meta y disfrutar de sus resultados. Pero si sientes que no estas aprendiendo quizás sea el momento de parar. Si como persona no estás avanzando quizás no merezca la pena. Incluso a veces con una buena cantidad de usuarios recurrentes sea mejor dejar el proyecto porque no obtienes nuevos usuarios a pesar deque el sector esté creciendo.

Abandona cuando el coste sea demasiado grande como para seguir. El coste te ayuda a cuantificar tus deseos de conseguir el objetivo. Que cantidad de sufrimiento estás dispuesto a pasar para llegar a tu meta. Siempre puedes abandonar proyectos en vista de uno mejor pero a su vez ten en mente que siempre abandonar proyectos a la mitad nunca terminaras ninguno. Abandona cuando estés intentando convencer a alguien de algo mediante tus actividades. Abandona cuando no sea divertido, cuando no te lo pases bien, cuando no disfrutes. Persiste si consigues conectar tu sueño con la meta. Un objetivo alineado a la meta te permitirá persistir duros y largos periodos de tiempo, de lo contrario te va a ser más fácil abandonar. Desistir no es malo de por sí. Renunciar a alcanzar un objetivo es lo malo. No renuncies cuando tengas opciones a alcanzar una meta con un coste asumible. No abandones por falta de persistencia cuando las cosas se ponen feas.

Cuando no creas en lo que trabajas abandona. Si no crees en tu proyecto nadie lo hará por ti. Tienes que estas motivado para trabajar. Si hay algo en tu tripa que te hace sentir incomodo (que no sean gases :P) abandona. La intuición es un elemento de la vida del que no se presta mucha atención. La intuición está infravalorada. Estos sentimientos que tienes en la barriguita te indican muchas cosas. Es una de las fórmulas que tiene la natura para informarte de lo que estás haciendo no está bien. Si tienes esta percepción abandona. Si tienes un mal presentimiento es que algo no está yendo bien aunque no puedas identificar el motivo por el que te sientes así abandona. La intuición es lo que percibe cada célula de tu cuerpo basado en experiencias pasadas.

A veces tenemos que analizar nuestros objetivos y preguntarnos honestamente que es lo que realmente queremos obtener. Por ejemplo, si quieres ser jugador de baloncesto de la NBA quizás no tengas los genes o no estés dispuesto a seguir todas las limitaciones que te imponen para triunfar en el mundo de la élite deportiva. Pero si lo que quieres es trabajar en la NBA quizás puedas ser entrenador o fisioterapeuta. Si lo que quieres es estar involucrado quizás puedas conseguir comprar un equipo, pero si tu objetivo real es ser famoso quizás puedas trabajar duro para ser estrella de rock. Puedes triunfar y ser famoso en muchos otros ámbitos. Quizás te resulte más fácil ser famoso en otras industrias consiguiendo así tus sueños.

Nota: Para también se requieren oportunidades y la suerte. Ambos juegan un papel importante. Probablemente mas importante de lo que muchos queramos reconocer.

Optimizadores de tensor flow

Continuando el anterior post dónde introducí tensor flow hoy vengo con los optimizadores de funciones. Tensor flow ofrece optimizadores que cambian las variables para minimizar la funcion de perdida (loss function). El más simple es el de gradiente descendiente. Computan las derivadas simbólicas (symbolic derivatives) simplemente usando el modelo y la función tf.gradients. Por ejemplo:

optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
sess.run(init) # reset values to incorrect defaults.
for i in range(1000):
sess.run(train, {x:[1,2,3,4], y:[0,-1,-2,-3]})
print(sess.run([W, b]))
los resultados finales
[array([-0.9999969], dtype=float32), array([ 0.99999082],
dtype=float32)]

El modelo completo para la regresión linal es:

import numpy as np
import tensorflow as tf
# Model parameters
W = tf.Variable([.3], tf.float32)
b = tf.Variable([-.3], tf.float32)
# Model input and output
x = tf.placeholder(tf.float32)
linear_model = W * x + b
y = tf.placeholder(tf.float32)
# loss
loss = tf.reduce_sum(tf.square(linear_model - y)) # suma de los cuadrados
# optimizer
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
# training data
x_train = [1,2,3,4]
y_train = [0,-1,-2,-3]
# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init) # reset values to wrong
for i in range(1000):
sess.run(train, {x:x_train, y:y_train})
# evaluate training accuracy
curr_W, curr_b, curr_loss  = sess.run([W, b, loss], {x:x_train, y:y_train})
print("W: %s b: %s loss: %s"%(curr_W, curr_b, curr_loss))
# When run, it produces
#W: [-0.9999969] b: [ 0.99999082] loss: 5.69997e-11

tf.contrib.learn te simplifica la vida con las funciones: ejecución, entrenamiento, iteraciones, evaluaciones entre otros

import tensorflow as tf
import numpy as np
features = [tf.contrib.layers.real_valued_column("x", dimension=1)]
estimator = tf.contrib.learn.LinearRegressor(feature_columns=features)
x = np.array([1., 2., 3., 4.])
y = np.array([0., -1., -2., -3.])
input_fn = tf.contrib.learn.io.numpy_input_fn({"x":x}, y, batch_size=4,
num_epochs=1000)
estimator.fit(input_fn=input_fn, steps=1000)
print(estimator.evaluate(input_fn=input_fn))
# Result: {'global_step': 1000, 'loss': 1.9650059e-11}

Reducir el tamaño de las imágenes insertadas en un documento de Latex

El otro día estaba escribiendo mi tesis en latex y me di cuenta que las páginas que tenían figuras tardaban mucho en cargar. Llegué a la conclusión que era debido a la complejidad de la imagen. Por lo que después de hacer un poco de investigación encontré la solución. Tenia que convertir todos los pdf a png (u otro tipo de formato de imagen).

El script convierte todos archivos de un directorio de pdf a png. Con cada iteración del script convierte cada archivo. Cara archivo tarda unos cinco minutos, así que paciencia.

for file in /Users/roc/Desktop/th/aux/* #hesis-plots/*
do
  y=${file%.*}
  convert -density 300 $y.pdf $y.png
done

Obtener las “chains” separadas de un simple PDB

El otro día peleándome con TM-align para conseguir alineaciones de distintos pdbs que parecieran razonables me di cuenta que dicho programa tiene problemas con las proteínas multi-dominio. La solución que le encontré fue en bajarme los PDBs y luego separar las chains. Aquí os dejo el script.


import re
import os

#Idea: https://www.biostars.org/p/59715/

list_path  =  'list-DLG4_HUMAN.txt'
db_path    =  '/n/scratch2/rr191/databases/pdb2/'

with open(list_path, 'r') as f_pdb:
    for pdb in f_pdb:

        #Getting the info from the pdb to download
        structure = pdb.split(':')[0].lower()
        chain = pdb.split(':')[1].upper()[0]

        #downloading the pdbs
        if(not os.path.isfile(db_path+structure+'.pdb') or True):
            _ = os.popen('wget -O '+db_path+structure+'.pdb https://files.rcsb.org/download/'+structure+'.pdb > /dev/null 2>&1').read()

        with open(db_path+structure+'.pdb', 'r') as f:
            with open(db_path+'chains/'+structure+'_'+chain+'.pdb', 'w') as fo:
                for line in f:
                    #selecting the atoms from the desired chain and writing them in a new file
                    if 'ATOM' in line and ' '+chain+' ' in line:
                        fo.write(line)

Como ejecutar DALI para el alineamiento de proteínas con las librerías de Fortran originales

DALI es un programa de comparación de estructuras de proteínas de finales del siglo pasado. A pesar de ser un programa ampliamente usado, el código hace décadas que no ha sido tocado por lo que sigue usando librerías de unos 20 años de antigüedad. Librerías Fortran que ya no están en la versión actual del gcc.

El problema que me daba es:

error while loading shared libraries: libg2c.so.0: cannot open shared object file: No such file or directory

Como quería usar este programa tuve que encontrar una solución. Al final lo que conseguí es instalar una versión antigua de gcc para poder usar las librerías usando el compilador antiguo de Fortran (gfortran).

Al final encontré la única solución. Consiste en instalar el compilador de GNU y después compilar y ejecutar dalilite usando la versión antigua.

Para empezar nos bajaremos la versión antigua del compilador de GNU, la versión gcc-3.4.6

wget https://ftp.gnu.org/gnu/gcc/

descomprimiremos el archivo comprimido, y crearemos el directorio dónde pondremos las librerías

tar -zxvf gcc-3.4.6.tar.gz
cd gcc-3.4.6
mkdir build
cd build

Configuraremos gcc-3.4.6

../configure --enable-shared –prefix=/cualquier/directorio --disable-multilib --disable-bootstrap # /cualquier/directorio puede ser por ejemplo /home/roc/herramientas/gcc-3.4.6

Ahora hacemos un build y lo instalamos. Esto va a tardar un rato y se instará en el directorio previamente seleccionado

make -j 4
make install

Ahora que ya tenemos nuestra copia de gcc-3.4.6 instalada en /cualquier/directorio necesitamos hacer las librerías visibles.

export PATH=/cualquier/directorio/bin:$
export LD_LIBRARY_PATH=/cualquier/directorio/

Ahora dalilite debería funcionar. Recuerda en recompilarlo con el Makefile. Además cada vez que quieras ejecutarlo deberías usar las dos lineas anteriores

Espero que os haya servido!

Introducción a TensorFlow

La web oficial de TensorFlow tiene muy buenos recursos. En esencia lo que hay en este post proviene del “get started” de la web oficial.

En el primer ejemplo importaremos TensorFlow. Crearemos dos constantes y las imprimiremos en pantalla.

import tensorflow as tf
node1 = tf.constant(3.0, tf.float32)
node2 = tf.constant(4.0) # También tf.float32 de forma implícita
sess = tf.Session()
print(sess.run([node1, node2]))
node3 = tf.add(node1, node2)
print("node3: ", node3) #Esta linea muestra las propiedades del tensor
print("sess.run(node3): ",sess.run(node3)) # Aquí se imprime el resultado

También podemos aplicar operaciones a los tensors. Las operaciones producen más tensores. En el siguiente ejemplo sumamos dos variables (tensores) y luego las sumamos. Un tensor es capaz de procesar listas también como veremos.

a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
adder_node = a + b
print(sess.run(adder_node, {a: 3, b:4.5})) # 7.5
print(sess.run(adder_node, {a: [1,3], b: [2, 4]})) # Itera sobre la lista: 3 y 7

Podemos multiplicar

add_and_triple = adder_node * 3.
print(sess.run(add_and_triple, {a: 3, b:4.5}))

E incluso podemos crear modelos lineales

W = tf.Variable([.3], tf.float32)
b = tf.Variable([-.3], tf.float32)
x = tf.placeholder(tf.float32)
linear_model = W * x + b

Las constantes son inicializadas con tf.constant, y su valor no puede ser cambiado. Contrariamente las variables son creadas usando tf.Variable y no son inicializadas en el inicio. Para inicializar las variables  tenemos que usar una función especial como en el siguiente ejemplo:

init = tf.global_variables_initializer()
sess.run(init)

Lo importante es usar init. Es un “handle” que inicia el grafo, inicializando las variables que hasta entonces habían permanecido sin inicializar.

Ya que la X es la variable podemos evaluar el modelo usando distintos valores simultáneamente de la siguiente manera:

print(sess.run(linear_model, {x:[1,2,3,4]}))
# Output: [ 0, 0.30000001, 0.60000002, 0.90000004]

La función de pérdida (loss function) puede medir la distancia entre el modelo actual y los datos proporcionados. Usaremos la función de pérdida estándar para hacer una regresión lineal que sume los cuadrados de las distancias entre el modelo actual y los datos. El modelo crea un vector en el que cada posición corresponde a una distancia de error. Cuando usamos tf.square estamos elevando al cuadrado el error. Luego sumamos los errores para crear un simple escalar que abstrae el error de todos los puntos usando tf.reduce_sum:

y = tf.placeholder(tf.float32)
squared_deltas = tf.square(linear_model - y)
loss = tf.reduce_sum(squared_deltas)
print(sess.run(loss, {x:[1,2,3,4], y:[0,-1,-2,-3]}))

El valor producido es:  23.66

Podríamos mejorar el modelo manualmente asignando nuevos valores a W para obtener resultados perfectos de -1 y 1. Una variables es inicializada por el valor proporcionado por tf.Variable pero puede ser cambiada si usamos operaciones como tf.assign. Por ejemplo, W=-1 y b=1 son los parámetros óptimos de nuestro modelo. Podemos cambiar W y b acordemente:

fixW = tf.assign(W, [-1.])
fixb = tf.assign(b, [1.])
sess.run([fixW, fixb])
print(sess.run(loss, {x:[1,2,3,4], y:[0,-1,-2,-3]})
#resultado: 0

Hemos adivinado el valor perfecto para W i b aunque este no es el objetivo de  machine learning. El objetivo es encontrar los parámetros correctos para el modelo automáticamente. Pero esto lo vais a encontrar en la próxima entrega 😉

Bonus: En matemáticas y en física, un tensor es cierta clase de entidad algebraica de varias componentes, que generaliza los conceptos de escalar, vector y matriz de una manera que sea independiente de cualquier sistema de coordenadas elegido. ( wikipedia )

Script en python para convertir secuencias de proteínas de Stockholm a fasta

Aquí os dejo un pequeño python script que convierte “multiple sequence alignments” del formato Stockholm a Fasta de una forma sencilla y rápida.

import sys
from Bio import SeqIO
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord 

if(len(sys.argv) <3):
    print('two arguments needed: input path, output path')
    exit(2) 

with open(sys.argv[1],'r') as inFile:
    with open(sys.argv[2], "w") as output_handle:
        SeqIO.write(list(SeqIO.parse(inFile,'stockholm')), output_handle, "fasta")

Texmaker al estilo de Sublime text (monokai)

Sublime text, aunque es un editor de texto que me gusta mucho, he estado buscando alternativas. He encontrado textmaker. Texmaker es  un editor de latex que nos permite compilar el documento pdf además de añadir otras interesantes features. Lo que no me gustaba era el tema (theme) que tenía por defecto. Así que buscando di con la solución. Usar el theme de Sublime text, llamado monokai.

Para cambiarlo simplemente tenemos que ir a $HOME/.config/xm1 (tanto en linux, como en MacOS y editar el fichero texmaker.ini y reemplazar las siguientes lineas de la principio del fichero:

Color\Background=@Variant(\0\0\0\x43\x1\xff\xff\0\0++66\0\0)
Color\Command=@Variant(\0\0\0\x43\x1\xff\xff&&\x8b\x8b\xd2\xd2\0\0)
Color\Comment=@Variant(\0\0\0\x43\x1\xff\xffllqq\xc4\xc4\0\0)
Color\Highlight=@Variant(\0\0\0\x43\x1\xff\xff\a\a66BB\0\0)
Color\Keyword=@Variant(\0\0\0\x43\x1\xff\xff\xdc\xdc\x32\x32//\0\0)
Color\KeywordGraphic=@Variant(\0\0\0\x43\x1\xff\xff\x85\x85\x99\x99\0\0\0\0)
Color\Line=@Variant(\0\0\0\x43\x1\xff\xff\a\a66BB\0\0)
Color\Math=@Variant(\0\0\0\x43\x1\xff\xff**\xa1\xa1\x98\x98\0\0)
Color\NumberGraphic=@Variant(\0\0\0\x43\x1\xff\xff\xcb\xcbKK\x16\x16\0\0)
Color\Standard=@Variant(\0\0\0\x43\x1\xff\xff\x83\x83\x94\x94\x96\x96\0\0)
Color\Todo=@Variant(\0\0\0\x43\x1\xff\xff\xd3\xd3\x36\x36\x82\x82\0\0)
Color\Verbatim=@Variant(\0\0\0\x43\x1\xff\xff\xb5\xb5\x89\x89\0\0\0\0)

Reducción de dimensiones: Principal Component Analysis (PCA)

Principal Component Analysis o PCA en corto es un método de reducción de dimensiones bastante conocido y comúnmente usado. Este método transforma ortogonalmente las observaciones (quizás relacionadas) en un conjunto de puntos linealmente no relacionados. De esta forma se consigue que el primer componente tenga la varianza mayor. El siguiente componente será el que tendrá la varianza mayor de los restantes y es ortogonal al anterior componente, y así sucesivamente. Este método es sensible a la escala de las variables. Para evitar que los valores sean un problema tendremos que escalar las variables estandardizándolos antes de usar PCA.

Generar una barra de progreso en ipython notebooks

Manual con código para generar una barra de progreso en nuestro código para saber en que porcentaje de compleción estamos sin llenar el output con números. Muchos de los que usáis jupyter (el nuevo ipython notebooks) podéis imprimir por pantalla la iteración en la que vuestro loop reside. Eso es solo posible para una cantidad pequeña de iteraciones. Cuando llegamos a varios miles se puede generar un output bastante engorroso. Googleando un poco encontré la solución. Este código nos genera una clase que luego podemos llamar para obtener la barra de progreso junto con el porcentaje completado.

import sys, time
try:
    from IPython.core.display import clear_output
    have_ipython = True
except ImportError:
    have_ipython = False

class ProgressBar:
    def __init__(self, iterations):
        self.iterations = iterations
        self.prog_bar = '[]'
        self.fill_char = '*'
        self.width = 40
        self.__update_amount(int(0))
        if have_ipython:
            self.animate = self.animate_ipython
        else:
            self.animate = self.animate_noipython

    def animate_ipython(self, iter):
        try:
            clear_output()
        except Exception:
            # terminal IPython has no clear_output
            pass
        print '\r', self,
        sys.stdout.flush(),
        self.update_iteration(iter + 1)
        
    def update_iteration(self, elapsed_iter):
        self.__update_amount((elapsed_iter / float(self.iterations)) * 100.0)
        self.prog_bar += '  %d of %s complete' % (elapsed_iter, self.iterations)

    def __update_amount(self, new_amount):
        percent_done = int(round((new_amount / 100.0) * 100.0))
        all_full = int(self.width - 2)
        num_hashes = int(round((percent_done / 100.0) * all_full))
        self.prog_bar = '[' + self.fill_char * num_hashes + ' ' * (all_full - num_hashes) + ']'
        pct_place = int((len(self.prog_bar) / 2) - len(str(percent_done)))
        pct_string = '%d%%' % percent_done
        self.prog_bar = self.prog_bar[0:pct_place] + \
            (pct_string + self.prog_bar[pct_place + len(pct_string):])

    def __str__(self):
        return str(self.prog_bar)
        

Y el siguiente código vemos un ejemplo de como llamaremos la clase para obtener la funcionalidad deseada

c = ProgressBar(1000)
for i in range(1000):
    c.animate_ipython(i)

Para los interesados encontré el código aquí.