Archivo de la categoría: Machine learning

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 )