PROGRAMANDO CON LA API DE BAJO NIVEL DE TENSORFLOW (I)

<  VOLVER
Por: admin
mayo 11, 2020
admin
mayo 11, 2020

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.

TENSORFLOW Y EL CÁLCULO DE GRADIENTES

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.

CÓMO FUNCIONA TENSORFLOW

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.

API DE PYTHON DE BAJO NIVEL DE TENSORFLOW

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.

Tensores

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.

  • El nombre identifica de forma única al tensor.
  • El rank es el número de dimensiones de un tensor. De forma que:
    • un tensor de 0 dimensiones (rank = 0) es un escalar (por ejemplo, tensor = 2)
    • otro tensor de 1 dimensión (rank = 1) es un vector (por ejemplo, tensor = [2, 7])
    • un tensor de 2 dimensiones (rank = 2) se trata de una matrix de n filas y m columnas (por ejemplo, tensor = [[2, 7], [3,5], [6, 1]]), etc.
  • El shape es el número de elementos en cada dimensión.
    • El tensor = 3 tiene rank = 0 y shape = ( ).
    • Un tensor = [2, 7] tiene rank = 1 y shape = (2).
    • El tensor = [[2, 7], [3, 5], [6, 1]] tiene rank = 2 y shape = (3, 2). Se puede dar el caso en que el rank sea conocido pero se desconozca el tamaño de 1 ó más dimensiones. Un ejemplo de esta situación se da cuando se realiza un entrenamiento y se conoce el shape del vector de features pero se deja sin fijar hasta el instante de la ejecución el tamaño de cada batch de ejemplos con los que se entrenará. Suponiendo que el vector de features de la entrada es de 32x32x1, como se pretende dejar sin establecer el shape del tamaño de batch, se utilizará la palabra reservada “None” para especificar su shape, quedando como resultado un tensor de shape (None, 32, 32, 1).
  • Por último, cada tensor también dispone de un tipo de datos, como por ejemplo, tf.float32, tf.int64, tf.string, etc.

Operaciones

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:

  1. Registrar la nueva operación en un fichero C++.
  2. Implementar la op en C++.
  3. De forma opcional, crear un wrapper en Python.
  4. También opcionalmente, escribir una función que calcule el gradiente de esa op.
  5. Probar dicha op.

Grafos

Un grafo está formado por un conjunto de objetos:

  • tf.Operation: representan las unidades de cómputo
  • tf.Tensor: se corresponden con las estructuras de datos que fluyen entre operaciones almacenando sus entradas y salidas.

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:

Primera fase: construcción del grafo

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).

Programando con la API de Bajo Nivel de Tensorflow

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”.

Programando con la API de Bajo Nivel de Tensorflow

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:

Programando con la API de Bajo Nivel de Tensorflow

Segunda fase: ejecución de operaciones del grafo

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í!

MÁSTER EXPERTO EN BIG DATA ANALYTICS

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.

Suscríbete a nuestra Newsletter

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.

    Estamos para ayudarte con cualquier duda, pequeña o grande

    Llámanos, escríbenos al email o por WhatsApp o inicia un chat en la web y hablamos

    chevron-down