Archivo de la etiqueta: machine learning

PyCon: Las tres charlas que me gustaron

El PyCon2018 fue del 9 al 17 de mayo en Cleveland. La conferencia nos dejó una gran cantidad de charlas interesantes. A mi personalmente me gustaron tres. Dos de machine learning y una de optimización de código. Aquí dejo los vídeos para que podáis echarles una ojeada. Además dejo un mini-resumen con cada vídeo.

A practical guide to Singular Value Decomposition in Python

Esta charla es una introducción a los SVD (Singular Value Decomposition). Los SVD descomponen cada punto en vectores y miden las diferencias basándose en el ángulo de separación entre los elementos. Daniel Pyrathon defiende el uso de este algoritmo gracias a la demostrada efectividad de Netflix. Como ejemplo pone a Netflix, dónde la mayoría de vídeos recomendados nos gustan. Nos gustan porque el algoritmo ha sabido encontrar similitudes entre otros usuarios y entre series/películas. La charla es amena y recomendable.

Fighting the Good Fight: Python 3 in your organization

Durante unos 30min muy entretenidos Jason Fried nos explica como entrenó la inteligencia artificial para aprender a jugar al Street fighter. Des del principio el conferenciante engancha y nos explica la pipeline usada dónde el ordenador aprende a “entender” la pantalla (barras de salud, tiempo, y los jugadores) y pasa a optimizar las acciones para maximizar la recompensa. Optimizando para conseguir la mayor recompensa el algoritmo encuentra combinaciones de movimientos para ganar a los sus oponentes.

Performance Python: Seven Strategies for Optimizing Your Numerical Code

Quizás esta sea la charla más técnica de las tres. Jake VanderPlas nos explica como podemos optimizar la ejecución de nuestro código. En la charla expone siete herramientas que los programadores podemos usar para optimizar nuestro código. Des del uso de librerías para manejar vectores de forma eficiente, hasta compiladores que transforman el código de Python a C. Pasando por herramientas para paralelizar el código. Numpy, Cython, Numba, y Dask son algunas de las herramientas mencionadas.

¿Que te parecieron a ti las otras charlas? ¿Tienes alguna que recomiendes?

Instalando tensorflow en un container de docker

Con el docker instalado podremos instalar el tensor flow en un container de docker. Ejecutaremos el siguiente comando para iniciar el container con tensor flow. La primera vez que lo ejecutemos docker se bajará todos los archivos necesarios para poder correr el container, por lo que por lo que puede tardar un poco en estar listo. A partir de la segunda vez ya tendremos todo el software requerido en el ordenador y se ejecutará sin ningún problema.

docker run -it -p 8888:8888 gcr.io/tensorflow/tensorflow

la opción -p 8888:8888 es usada para conectar el puerto interno de docker con el de la maquina física. Importante si queremos usar Jupyter notebooks. El formato es hostPort:containerPort. Y la url gcr.io/tensorflow/tensorflow contiene la imagen binaria para CPU. Hay otra con GPU, y sus respectivas con el código fuente. Aquí dejo una lista por si quieres la imagen con el codigo fuente o usar la versión GPU.

  • gcr.io/tensorflow/tensorflow: TensorFlow CPU
  • gcr.io/tensorflow/tensorflow:latest-devel: CPU y codigo fuente
  • gcr.io/tensorflow/tensorflow:latest-gpu: TensorFlow GPU
  • gcr.io/tensorflow/tensorflow:latest-devel-gpu: GPU codigo fuente

Instalando docker en Ubuntu

Esa va a a formar parte de una serie de posts. En los que voy a implementar algoritmos de inteligencia artificial en tensor flow. Y porque docker? Docker es un programa que crea virtualizaciones de sistemas operativos con un overhead muy reducido. Las virtualizaciones se llaman containers y requieren pocos recursos para poder virtualizar el entorno correctamente. La ventaja principal es que me permite crear automáticamente una instalación del sistema en cualquier ordenador sin mucho problema. La idea era actualmente hacerlo en el ordenador normal – por lo que seria innecesario usar docker – pero más adelante puede ser que use sistemas externos para realizar los trainings. Además permite separar distintas instalaciones en caso que hayas hecho modificaciones o quieras usar distintas versiones a la vez.

Primero empezaremos instalando la clave GPG oficial de docker

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

y añadiremos el repositorio en nuestras fuentes

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

Seguidamente actualizaremos la lista de paquetes disponibles para nuestra distribución

sudo apt-get update

y finalmente instalaremos docker (nótese que es docker-ce, las versiones anteriores tenian distintos nombres)

sudo apt-get install -y docker-ce

para comprobar que la instalación ha finalizado correctamente pondremos en la terminal:

sudo docker run hello-world

Que nos verificará que la instalación funciona correctamente. Cómo podéis comprobar requiere de sudo para poder usar el socket TCP para comunicarse con el sistema. Si queréis evitar esto. Tendremos que realizar unos pasos extra que pueden comprometer la seguridad del sistema.

El primer paso será crear un grupo

sudo groupadd docker

añadir el usuario al grupo

sudo usermod -aG docker $USER

para verificar que funciona y podemos evitar el uso de sudo cada vez tendremos que cerrar sesión y volver a logearnos. Una vez dentro ejecutaremos el “hello world” pero esta vez sin el sudo

docker run hello-world

Si nos sale un “permission denied” significa que algo no ha funcionado. Por el contrario si el comando se ha ejecutado correctamente se imprimirá por pantalla un mensaje algo largo incitandote a usar docker.

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}

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 )