Una selfie al estilo de la Inteligencia Artificial de Google

Hace algunos días llegó a mi correo un artículo [2] de pyimagesearch.com, en sitio de tutoriales sobre imágenes en Python del que ya he aprendido bastantes cosas. En este artículo hablaban sobre “la creación de imágenes artísticas usando sueños guiados” en base a los “Deep Dreams” o “Sueños Profundos” de Google, los que podemos describir como imágenes obtenidas desde las redes de Deep Learning de Google. Una explicación bastante completa de este tema puede ser encontrada en [3], pero para contextualizar podemos decir a grandes rasgos que Google está utilizando técnicas de Inteligencia Artificial para aprender patrones de una gran cantidad de imágenes (una GRAN cantidad de imágenes) para luego poder describir imágenes nuevas en base a los patrones aprendidos. Esto es lo que se conoce como Deep Learning, o el aprendizaje de patrones desde Redes Neuronales Artificiales de gran profundidad, que ya ha dado grandes logros como la descripción automatizada de imágenes en base a texto [7].

Una de las razones por las que se volvió llamativa la nueva investigación de Google para el público, fue que mediante estos modelos generados por el Deep Learning, se hizo el proceso inverso a la obtención de patrones. Es decir, en base a una imagen resultante, se le pide al sistema obtener los patrones que componen la imagen. Esto dio como resultado imágenes muy bizarras en las que la imagen original se convierte en una combinación de líneas y figuras, y luego de formas como ojos o caras de animales. La explicación completa desde Google se puede leer (en inglés) en [8].

Fuente: GoogleResearch Blog
Fuente: GoogleResearch Blog [8]

En el artículo que llegó a mi correo, se habla de un módulo de Python que permite utilizar este modelo generado por Google para producir una imagen usando otra imagen como guía. O sea, usamos una imagen de base y usamos otra imagen que orienta la búsqueda de patrones en el modelo de Google para que la imagen que entregamos se exprese como una combinación de patrones relacionados a la imagen que usamos de guía.

El módulo de Python que se nombra es bat-country, que se presenta en un artículo anterior del mismo sitio [4]. Por curiosidad, intenté instalarlo y aproveché de hacer un tutorial para registrar la experiencia.

Instalación de bat-country

Hay varias cosas que instalar antes de hacer el experimento. Voy a partir por lo que me jodió por más tiempo: instalar bat-country.

Instalar bat-country no es difícil, pero me quitó tiempo porque sus dependencias se demoran un rato en instalar (matplotlib, te estoy mirando a ti) y si uno no tiene ciertas dependencias de las dependencias, la instalación falla al final y hay que descargar todo de nuevo (sí, matplotlib, te sigo mirando a ti). Las dependencias de matplotlib que me hicieron tener que descargar todo de nuevo son freetype y png. Para los usuarios de sistemas debian como Ubuntu, encontré un tutorial de cómo instalarlas [6], pero como yo uso Fedora, los instalé con yum:

sudo yum install freetype-devel libpng-devel

Otra cosa que tuve que instalar antes de ejecutar el script de instalación de bat-country, fue scipy. Scipy es un conjunto de herramientas científicas para Python, entre las que se incluye el conocido módulo Numpy. Intenté instalar Scipy mediante pip, pero se puso pesado buscando otros módulos, así que como era tarde y yo quería ver luego si el experimento resultaba, lo instalé directamente desde Yum:

sudo yum install scipy

Ahora que estamos seguros de que la ausencia de freetype y png no nos va a obligar a descargar matplotlib de nuevo, empezamos a instalar bat-country (entiéndanme, con mi internet fue todo un asunto el descargar todo otra vez). Existen dos formas de instalar bat-country. Una es usando directamente los repositorios de pip, la herramienta para instalar módulos de Python. La otra es descargando directamente bat-country desde el repositorio de GitHub (y luego usando pip. Me gusta decir pip, suena chistoso).

Para instalar bat-country mediante pip:

pip install bat-country

Para instalar bat-country desde GitHub:

#Nos ubicamos en alguna carpeta de nuestro sistema y descargamos el repositorio
git clone https://github.com/jrosebr1/bat-country.git
#Descomprimimos el archivo
cd bat-country
pip install -r requirements.txt
python setup.py install

Mientras se instalan las dependencias del archivo requirements.txt podemos ir a darnos una vuelta por ahí, beber algo (esta vez fue sólo Pepsi) o ponernos a perder el tiempo en algo improductivo como Agar.io (aunque no lo hice esta vez. Fucking lag).

Ahora tenemos la biblioteca mágica instalada, ¿estamos listos para probar la magia?

Instalando Caffe [8]

La verdad es que no estamos listos. El poder utilizar un modelo de Deep Learning no es una cosa sencilla, pues se requiere una gran arquitectura funcionando por debajo. En este caso, bat-country se basa en el framework Caffe, desarrollado en Berkeley.

Caffe es un framework de Deep Learning. Es un conjunto de herramientas diseñado para implementar aplicaciones al nivel del estado-del-arte en aprendizaje automatizado, capaz de funcionar con un altísimo desempeño aprovechando al máximo los recursos de la máquina. Tiene la opción de funcionar sobre GPU, pero este no es mi caso… -se va a un rincón y llora-.

Para instalar Caffe, debemos descargarlo desde GitHub y compilarlo en nuestra máquina. Para eso, nos ubicamos en alguna carpeta en la que queramos instalarlo. Yo tengo una carpeta llamada src en mi carpeta personal para probar programas, así que lo descargué ahí.

cd ~/src
git clone https://github.com/BVLC/caffe.git
#Descomprimimos el archivo y entramos a la carpeta
cd caffe-master

Antes de compilar Caffe, se deben instalar algunas dependencias. Estas dependencias salen explicadas en la página oficial de instalación de Caffe. Aquí hay un tutorial para Ubuntu [10] y uno para Fedora, que es el que pongo a continuación [11].

sudo yum install protobuf-devel leveldb-devel snappy-devel opencv-devel boost-devel hdf5-devel
#Existen otras dependencias que se aplican para versiones recientes
sudo yum install gflags-devel glog-devel lmdb-devel
#Si no se encontraron ciertas dependencias, se pueden instalar las siguientes
# glog
wget https://google-glog.googlecode.com/files/glog-0.3.3.tar.gz
tar zxvf glog-0.3.3.tar.gz
cd glog-0.3.3
./configure
make && make install
# gflags
wget https://github.com/schuhschuh/gflags/archive/master.zip
unzip master.zip
cd gflags-master
mkdir build && cd build
export CXXFLAGS="-fPIC" && cmake .. && make VERBOSE=1
make && make install
# lmdb
git clone git://gitorious.org/mdb/mdb.git
cd mdb/libraries/liblmdb
make && make install

Para que Caffe funcione, necesita un módulo BLAS (Basic Linear Algebra Subprograms) funcionando en el sistema. Este tipo de módulos sirven para paralelizar operaciones vectoriales y matriciales a bajo nivel. No me manejo en el tema, así que no voy a intentar profundizar mucho (igual les dejo el artículo de Wikipedia, por si acaso: [12]). Existen varias alternativas para instalaciones de módulos BLAS como ATLAS, OpenBLAS y MKL (que es específico para CPUs Intel). El que viene por defecto en Caffe es ATLAS, pero para hacer la instalación más rápida, yo instalé OpenBLAS desde Yum:

sudo yum install openblas openblas-devel

(Nótese que es importante instalar openblas-devel, creo que openblas-dev en sistemas Debian, porque ahí se incluyen las bibliotecas que Caffe importará al compilar).

Ahora deberíamos estar dentro de la carpeta de caffe (caffe-master en mi caso) para empezar la compilación. Para compilar, necesitamos primero copiar la plantilla del Makefile que se incluye en Caffe y configurar ciertos parámetros. Primero, debemos seleccionar si utilizaremos la GPU o la CPU. Luego debemos seleccionar qué módulo de BLAS utilizaremos y luego indicar las rutas de las bibliotecas del módulo BLAS.

#Copiamos la plantilla de Makefile incluida en la carpeta de Caffe
cp Makefile.config.example Makefile.config
#Luego se configura el Makefile (explicación más abajo)
#Se ejecutan las instrucciones make
make all
make test
make runtest

Las configuraciones que hay que hacer en el Makefile son:

  1. Seleccionar la opción de compilar solamente con CPU (si tienen GPU pueden saltarse este paso).  Para eso hay que descomentar la línea que dice CPU_ONLY := 1
  2. Seleccionar el módulo BLAS. Bajo una línea que dice “#BLAS choice:” hay que modificar para que diga “BLAS := open” si estamos usando openblas, o las opciones que ahí salen indicadas para el módulo correspondiente de BLAS.
  3. Si cambiamos la opción de BLAS que viene por defecto, debemos indicar las rutas en las que se encuentran las bibliotecas a incluir. En mi caso, tuve que especificar estas dos líneas (recuerdo que así es para Fedora. Para otro sistema quizás las rutas sean distintas) “BLAS_INCLUDE := /usr/include/openblas/” y “BLAS_LIB := /usr/lib/”.

Habiendo hecho lo anterior, se ejecutan los comandos make y se espera que pase lo mejor. Si no aparece ningún error, significa que al fin Caffe está compilado y listo para funcionar.

Preparar los wrappers de Python (pycaffe)

No se desanimen, esto es cortito. Para poder correr bat-country, se deben activar los wrappers de Python. Los wrappers son funciones que encapsulan la llamada a una aplicación para usarse en otro lenguaje. Esto nos deja llamar a Caffe desde Python.

Primero debemos instalar las dependencias de Python necesarias para hacer funcionar Caffe (recuerden que seguimos dentro de la carpeta de Caffe). Aquí vuelve a aparecer el compadre pip:

for req in $(cat requirements.txt); do pip install $req; done

Luego, añadimos la ruta de Caffe a la variable de entorno PYTHONPATH para que Python pueda encontrar el módulo de Caffe. Ejecutamos lo siguiente en la consola:

export PYTHONPATH=$HOME/src/caffe-master/python:$PYTHONPATH

Esta instrucción modificará la variable de entorno sólo mientras la consola esté abierta. Para no tener que ejecutarla siempre, añadí esa instrucción al final de mi archivo .bashrc, lo que es totalmente opcional.

Después de esto, llamamos a make para generar el wrapper pycaffe:

sudo make pycaffe

Con esto ya podemos usar Caffe desde Python, y a la vez, el módulo bat-country.

Usando bat-country

En [8] se muestra el siguiente código, con el que se puede probar el módulo bat country:

# import the necessary packages
from batcountry import BatCountry
from PIL import Image
import numpy as np
import argparse

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-b", "--base-model", required=True, help="base model path")
ap.add_argument("-l", "--layer", type=str, default="inception_4c/output",
	help="layer of CNN to use")
ap.add_argument("-i", "--image", required=True, help="path to base image")
ap.add_argument("-g", "--guide-image", required=True, help="path to guide image")
ap.add_argument("-o", "--output", required=True, help="path to output image")
args = ap.parse_args()

# we can't stop here...
bc = BatCountry(args.base_model)
features = bc.prepare_guide(Image.open(args.guide_image), end=args.layer)
image = bc.dream(np.float32(Image.open(args.image)), end=args.layer,
	iter_n=20, objective_fn=BatCountry.guided_objective,
	objective_features=features)
bc.cleanup()

# write the output image to file
result = Image.fromarray(np.uint8(image))
result.save(args.output)

Ese código se debe guardar en un archivo .py. Antes de ejecutarlo hay que hacer una última cosa. No se puede empezar la fiesta si no está el anfitrión principal: el modelo de Deep Learning generado por Google. Este modelo se puede descargar mediante Caffe. Para descargar el modelo abrimos una consola y nos ubicamos en la carpeta donde quedó Caffe. Para descargar el modelo ejecutamos un script que viene incluido de antemano:

./scripts/download_model_binary.py models/bvlc_googlenet/

Ese  código se encargará de descargar el modelo y guardarlo en la carpeta “models” como la carpeta “bvlc_googlenet”.

Ahora ya podemos ejecutar bat-country. Para ejecutar el código, se necesita especificar cuatro cosas:

  1. El modelo base: Aquí es donde especificamos el modelo con el que vamos a procesar las imágenes. Lo especificamos con “-b nombre_de_modelo” o “–base-model nombre_de_modelo”. Este “nombre_de_modelo” debe ser la ruta de la carpeta del modelo que vamos a usar. Para eso se puede apuntar con la ruta completa a la carpeta “models/bvlc_googlenet” dentro de Caffe, pero para no hacer la ruta tan larga, yo copié la carpeta “bvlc_googlenet” a la misma carpeta del script de Python. Al final esta parte quedó como “-b bvlc_googlenet”.
  2. La imagen de entrada: Esta imagen de entrada es la que queremos “interpretar” por el modelo. En este caso yo me tomé una foto (a fin de cuentas, todo esto fue con el fin de conseguir una selfie engorrosa y poco convencional) y la especifiqué con “-i imagen.jpg”.
  3. La imagen de guía: Para que la búsqueda de patrones para describir la imagen no sea completamente exhaustiva, le entregamos una imagen de guía, que va a darle prioridad a los patrones que se encuentren dentro de ella. Por ejemplo, si ponen una imagen de ojos, se puede conseguir una de esas composiciones bizarras en las que las figuras se componen de muchas formas de ojos. Se especifica con “-g imagen”
  4. La imagen de salida: Bueno, la descripción lo dice todo. Se especifica con “-o archivo_de_salida”.

En una línea de código, y asumiendo que el archivo de Python se llama bat-country-test.py y las imágenes están en la misma carpeta, se puede ejecutar todo con:

python bat-country-test.py -b bvlc_googlenet -i input.jpg -g guide.jpg -o output.jpg

Después hay que esperar un rato. Para generar la imagen de abajo, en mi PC se demoró como 400 segundos.

En mi caso, usé las siguientes imágenes:

Primero, una selfie como imagen de entrada.

Sé que tengo cara de zombie. Pero no se puede pedir mucho a las tres de la mañana.
Sé que tengo cara de zombie. Pero no se puede pedir mucho a las tres de la mañana.

Luego, pillé una imagen de un bosque en Google. Me gustan los bosques. Esta fue la imagen de guía.

¿Cierto que son bonitos los bosques?
¿Cierto que son bonitos los bosques?

Y taratarán… esta cosa fue lo que resultó.

No, no hagan chistes sobre Jesús. Mantengamos este blog como un espacio laico, por favor.
No, no hagan chistes sobre Jesús. Mantengamos este blog como un espacio laico, por favor.

Conclusión

Sí, es una forma terrible de conseguir una foto de perfil. Lo interesante, es que a través de todo este experimento me pude acercar a un montón de tecnologías nuevas. Sirvió un poco para ver cómo un modelo de aprendizaje profundo puede lograr reconstruir imágenes en base a patrones con los que se haya entrenado. Hasta ahora era muy poco lo que se conocía sobre los patrones generados internamente en las redes neuronales artificiales. El hecho de poder visualizarlas, ayuda de gran manera a que podamos entender mejor su funcionamiento y sus capacidades, y también, por qué no, entender un poco mejor las redes neuronales naturales que tenemos en la ca’eza.

Referencias:

  1. pyimagesearch.com
  2. Generating art with deep guided dreaming
  3. Las increíbles imágenes de los sueños de la inteligencia artificial de Google
  4. bat-country: an extendible, lightweight Python package for deep dreaming with Caffe and Convolutional Neural Networks
  5. bat-country en GitHub
  6. Matplotlib and its local dependencies
  7. How Google “Translates” Pictures into Words Using Vector Space Mathematics
  8. http://googleresearch.blogspot.com/2015/06/inceptionism-going-deeper-into-neural.html
  9. Caffe
  10. Instalación de Caffe para Ubuntu
  11. Instalación de Caffe para Fedora
  12. BLAS en Wikipedia
Anuncios