Tras una breve introducción en la que os mostramos el objetivo de DIA4RA y nuestra intención de hacer un recorrido por las principales herramientas que estamos empleando, ha llegado el momento de ponernos manos a la obra. Y qué mejor manera de comenzar que hacerlo por el tejado, la librería que vamos a utilizar para implementar los algoritmos que dotarán de inteligencia al robot. Como habréis adivinado por el título, se trata de Tensorflow.
A diferencia de lo que muchos podrían pensar, esta librería desarrollada por Google no es únicamente aplicable a casos de uso de Inteligencia Artificial. En realidad, es un framework de computación numérica que, entre muchas otras posibilidades, permite el cálculo de gradientes de forma automática. Muchos algoritmos de Deep Learning emplean como base de aprendizaje la técnica de “Gradient Descent” que, a muy grandes rasgos, consiste en intentar encontrar el valor mínimo global de la función de error del problema que se pretende aprender a solucionar. Para ir avanzando en la búsqueda de ese valor mínimo, en cada paso de dicho proceso de aprendizaje se calcula el gradiente de la función de error en ese punto, con el objetivo de conocer la dirección hacia donde hay que dirigirse para ir minimizando el error cometido. Como Tensorflow facilita este cálculo y tiene a un gigante como Google manteniendo este proyecto, se ha popularizado a la hora de aplicarse en el ámbito de las Redes Neuronales Artificiales.
Tensorflow es multi-plataforma y para ello, proporciona un motor denominado “Tensorflow Distributed Execution Engine” cuyo “core” está implementado en C++. Su objetivo es permitir la ejecución en múltiples arquitecturas como dispositivos móviles, sistemas embebidos, CPUs, GPUs… Incluso TPUs (Tensor Processing Units), que es un HW desarrollado por Google optimizado para realizar de forma muy eficiente operaciones con “tensores”. Por encima de esta capa se asientan “frontends” en distintos lenguajes de programación como Python, C++, Java, Julia, Go, Javascript, etc. Pero, sin duda, la versión más utilizada es la de Python que además ofrece APIs con diversos niveles de abstracción. En este artículo vamos a hacer un breve recorrido por la API de Python de Bajo Nivel de Tensorflow y en los siguientes nos centraremos en una de las APIs de Alto Nivel que más se está impulsando desde el equipo de desarrolladores de Tensorflow. Esta coincide con la que estamos empleando para codificar los algoritmos en DIA4RA: la Estimator API. La principal razón de haber tomado esta elección se debe a que permite emplear el mismo código tanto para entrenar modelos y hacer inferencia en local como para subir el código al Cloud y realizar un entrenamiento distribuido y posteriormente exportar dicho modelo ya entrenado y emplearlo (servirlo) para poder realizar predicciones desde la nube. Otra API de Alto Nivel de Tensorflow bastante conocida por su simplicidad es Keras, que también se utilizará en este proyecto pero siempre combinada con la estructura de programación de la Estimator API para mantener un mismo estilo entre diferentes modelos.
Como ya tendréis ganas de empezar a cacharrear con Tensorflow, vamos a comenzar mostrando algunos de los componentes esenciales de su API de Bajo Nivel.
El elemento fundamental del que toma su nombre Tensorflow es el tensor y se implementa mediante un nodo tf.Tensor. Puede definirse como un array n-dimensional y se corresponde con su estructura básica de almacenamiento de datos. Cada tensor tiene un nombre, un rank, un shape y un tipo.
Los datos contenidos en los tensores se corresponden con las entradas de operaciones que realizan cálculos con dicha información. Cuando se consulta documentación de Tensorflow, a menudo se verá que se hace referencia a las operaciones empleando el término ‘ops’ y formalmente genera un nodo tf.Operation. Las operaciones son nodos que toman cero o más tensores como entrada, realizan cálculos a partir de esos datos y devuelven cero o más tensores como salida. Para instanciar una op hay que llamar a su constructor, que recibirá los tensores necesarios. Por ejemplo, una operación como tf.multiply puede tomar 2 entradas y cuando sea ejecutada devolverá el resultado de su producto.
import tensorflow as tf import numpy as np # Inicialización de arrays de numpy que actuarán como los tensores de entrada de la op a = np.array([2, 3], dtype=np.int32) b = np.array([4, 5], dtype=np.int32) # Creación de la op de multiplicación resultado = tf.multiply(a, b) |
Si se desea añadir una nueva op que no esté presente entre las ofrecidas por Tensorflow, será necesario seguir los pasos indicados en esta url de la documentación oficial.
Resumiendo, el proceso conlleva realizar las siguientes acciones:
Un grafo está formado por un conjunto de objetos:
Los programas de Tensorflow que no emplean el modo Eager Execution (en esta serie de artículos veremos en qué consiste) se componen de 2 fases diferenciadas:
La primera de ellas es la construcción del grafo de operaciones. Automáticamente, Tensorflow crea un grafo por defecto. Cada vez que se declara una operación, será añadida también de forma automática al grafo por defecto (con la excepción, de la que hablaremos a continuación, de que otro grafo se haya fijado momentáneamente como el grafo por defecto).
Si se define la operación “resultado” y se consulta si pertenece al grafo por defecto, la respuesta será “True”.
Pero también existe la posibilidad de crear otros grafos mediante la instrucción tf.Graph(). Además, como se comentó anteriormente, se puede establecer temporalmente uno de esos grafos (“g”) como el grafo por defecto mediante un bloque “with”. Si definimos operaciones dentro del ámbito de dicho bloque “with”, esas operaciones serán añadidas al grafo “g”.
En la siguiente captura, se ha creado un grafo “g” y se ha establecido mediante un bloque “with” como el grafo por defecto. Además se ha declarado una operación “resultado2” que será añadida al grafo “g”. Cuando se consulte si “resultado2” pertenece al grafo por defecto se obtendrá un “False”. Pero cuando se compruebe si pertenece al grafo “g” la respuesta será “True”.
Un aspecto fundamental del funcionamiento de Tensorflow es que durante la fase de construcción del grafo ninguna operación es evaluada. Solo se añaden dichas operaciones al grafo o grafos. Por lo que si se intenta obtener el valor de la op “resultado” lo único que se obtendrá es la estructura de ese tensor, como puede observarse en la siguiente imagen:
La segunda de las fases de las que se compone un programa de Tensorflow es la de ejecución de las operaciones del grafo. Para llevar a cabo esta etapa será necesario crear un objeto tf.Session().
Como AIDA reclama nuestra atención, en los próximos artículos de esta serie continuaremos mostrando la forma de crear tanto sesiones como el resto de los componentes de lo que se puede considerar el Core de Tensorflow. ¡Os esperamos por aquí!
Gracias al Master en Big Data Analytics 100% Online tendrás amplios conocimientos sobre las herramientas y técnicas analíticas necesarias para la modelización de los principales retos de negocio, con el fin de mejorar la toma de decisiones a través de los datos y el conocimiento.
Recibe nuestra programación mensual de eventos online y la apertura de nuevas convocatorias de cursos
En Datahack Consulting SL trataremos los datos que nos facilites con la finalidad de enviarte información relacionada con tu solicitud sobre nuestros servicios, así como enviarte comunicaciones informativas sobre nuestra actividad. Podrás ejercer los derechos de acceso, rectificación, limitación, oposición, portabilidad, o retirar el consentimiento enviando un email a administracion@datahack.es. También puedes solicitar la tutela de derechos ante la Autoridad de Control (AEPD). Puedes consultar información adicional y detallada sobre protección de datos en nuestra Política de Privacidad.
Llámanos, escríbenos al email o por WhatsApp o inicia un chat en la web y hablamos