Cómo montar una Plataforma Cloud de Machine Learning sin gastar dinero

Mauro Pereyra
Fretebras Tech
Published in
16 min readMay 28, 2021

--

El Machine Learning es una rama de la Inteligencia Artificial que viene creciendo de manera agigantada desde ya hace algún tiempo. Hoy en día es normal ver ofertas de empleo relacionadas con ello, y también escuchar casi a diario sobre el uso de esta técnica para resolver una infinidad de problemas bien diferentes entre sí (pero idénticos en el modo de resolverlos).

Nuestra primera aproximación como desarrolladores al Machine Learning suele ser un poco frustrante, debido principalmente a la cantidad y complejidad de los conceptos nuevos que involucra. Además, requiere de cierto estudio y tiempo lograr unir los conceptos y obtener una visión clara sobre el proceso de entrenamiento y uso de los modelos como un todo.

Este artículo surge entonces, como un medio para lograr que esa visualización integral del proceso sea más amena y que la comprensión de los procesos, actividades, componentes y flujos de información involucrados sea más simple y rápida. No me voy a centrar en enseñar código, sino más bien, voy a brindar una guía y algunos consejos que te van a ayudar a montar tu propia plataforma en la nube que te permita entrenar y usar redes neuronales sin la necesidad de invertir dinero.

La plataforma que vamos a describir se basa en la composición de soluciones cloud existentes (usa procesamiento y almacenamiento de terceros), hace uso de Aprendizaje Supervisado, Redes Neuronales Convolucionales, TransferLearning y además, es 100% gratuita!
El objetivo de la misma, en nuestro caso, es el de detectar objetos en tiempo real a través de una aplicación móvil.
Lo ideal es implementar la plataforma desde un comienzo con la idea de que sea genérica, configurable y extensible. Con genérica nos referimos a que posea la capacidad de poder entrenarse para detectar cualquier tipo de objeto (que no se encuentre “atada” a un objeto en particular).

Deteccion de objetos en tiempo real

Para entender cuáles actividades se deben llevar a cabo en la plataforma vamos a comenzar describiendo cómo se realiza el entrenamiento en las Redes Neuronales Artificiales y en las Redes Neuronales Convolucionales.

Entrenamiento de una Red Neuronal Artificial (ANN)

Para lograr que una red neuronal realice la tarea deseada, es necesario entrenarla. El entrenamiento consiste en ir modificando constantemente los valores de sus parámetros (pesos y bias) de manera de ir obteniendo mejores resultados de manera progresiva. Para ello, lo que se hace es introducir datos de entrenamiento en la red y en función del resultado que se obtenga se van ajustando los parámetros de acuerdo al error obtenido y en función de cuánto haya contribuido cada neurona a dicho resultado.
Este método es conocido como backpropagation (propagación hacia atrás) y gracias a él conseguimos que la red neuronal aprenda.
Podemos resumir el proceso de entrenamiento de la siguiente manera:

  1. Se eligen valores aleatorios para los parámetros de la red (pesos y bias)
  2. Para cada pase completo por la red, ida y vuelta, del conjunto de datos de
    entrenamiento (epoch):
    a) Se realiza el forward propagation (propagación hacia adelante) de los datos (la entrada se propaga capa por capa a través de la red hasta calcular la salida final de la red)
    b) Se calcula el coste o pérdida (la diferencia entre el resultado obtenido y el resultado esperado)
    c) Se realiza la propagación hacia atrás, para propagar el coste o perdida a
    cada parámetro de la red
    d) Se actualizan los parámetros de la red utilizando la técnica Gradient Descent para lograr que el coste se vaya minimizando en los sucesivos entrenamientos
    e) Se vuelve al paso 2a hasta que se alcance el número de epoch establecido.

Entrenamiento de una Red Neuronal Convolucional (CNN)

El entrenamiento de una CNN es similar al de las ANN. Si bien existe cierta complejidad adicional debido al uso de nuevas capas, el entrenamiento es muy parecido: en cada iteración se realiza una propagación hacia adelante de los datos a través de la red, se obtiene un resultado, se lo compara con el resultado esperado y se transmite el error hacia atrás mediante el uso de la propagación hacia atrás.
En el caso de las ANN se actualizan los pesos de las conexiones de las
neuronas; en cambio, en las CNN se actualizan los pesos de los filtros y de las capas totalmente conectadas que se encuentran al final de la red.

Aquí me gustaría mencionar unos conceptos, los cuales están relacionados con el entrenamiento de los modelos y es importante tenerlos presentes: el overfitting, el transfer learning y el uso de datasets “ya creados”.
El overfitting ocurre cuando un modelo “memoriza” o aprende demasiado bien los datos utilizados durante el entrenamiento, ocasionando que tenga dificultades a la hora de reconocer datos nuevos. El overfitting puede ser causado como consecuencia de un sobre-entrenamiento del modelo o por la existencia de muestras que resulten no ser del todo representativas. Para intentar reducir este problema existen algunas estrategias, como por ejemplo la ampliación del conjunto de datos. En el caso que no sea posible la obtención de nuevos datos, se puede hacer uso de la técnica de aumento, la cual consiste en generar nuevas imágenes a partir de las ya existentes a través de la aplicación de diferentes transformaciones (zoom, ruido, cambio de brillo y color, etc.).
El Transfer Learning es una técnica muy utilizada en Machine Learning que consiste en utilizar un modelo ya entrenado (generalmente con miles o
millones de datos) como punto de partida para resolver nuestro problema. Esta técnica nos brinda varias ventajas, como por ejemplo que se necesita menor cantidad de datos de entrenamiento y que el tiempo y los recursos para entrenar el modelo disminuyen drásticamente.
Los modelos ya entrenados suelen utilizar arquitecturas conocidas, como
MobileNet, ResNet, SSD, Inception y Faster RCNN. Además, suelen estar entrenados en enormes datasets, como COCO, Open Images e ImageNet
por citar algunos ejemplos.
En cuanto al uso de datasets ya creados, los mismos resultan muy útiles, pero su uso depende del problema a resolver. El principal problema de entrenar modelos utilizando estos datasets es que las imágenes que contiene son imágenes obtenidas bajo condiciones controladas, lo que conlleva a que la red neuronal se entrene con imágenes “perfectas”, en vez de con imágenes del “mundo real”. Eso genera que cuando el modelo tenga que inferir imágenes reales su precisión sea baja.

Etapas del Machine Learning

Cualquier actividad en Machine Learning involucra al menos 3 etapas: el armado del conjunto de datos a utilizarse en el entrenamiento, el entrenamiento y por último, el uso del modelo entrenado para inferir nuevos datos.

Etapas básicas del Machine Learning

Para lograr que la plataforma que deseamos construir abarque el proceso completo de entrenamiento y uso del modelo de Machine Learning es necesario agregar sub-tareas, tal como se muestra en la siguiente imagen:

Actividades por etapa

Allí se observan las 3 actividades principales: el armado del dataset de imágenes, el entrenamiento de la red neuronal y el uso (y previo deploy) del modelo generado por parte de la aplicación móvil.

  • El armado del dataset incluye la obtención, el etiquetado y el aumento de las imágenes a ser utilizadas para el entrenamiento.
  • El entrenamiento es un proceso iterativo durante el cual el algoritmo provee información y diferentes métricas al usuario referidas al desempeño del modelo que se está entrenando.
    En base a esa información el usuario puede optar por realizar ajustes en la red, en los parámetros, en los datos de entrada, o incluso puede optar por utilizar un modelo diferente, en el caso que los resultados devueltos no sean satisfactorios.
  • El deploy del modelo consiste en dos actividades. La primera es la generación del modelo a partir de los archivos generados durante el entrenamiento. La segunda actividad es el almacenamiento del modelo en un servicio de almacenamiento cloud.
  • Por último, el uso del modelo por parte de la aplicación contempla la sincronización (descarga y actualización) del modelo en el teléfono celular y su utilización.

Almacenar un modelo de machine learning en la nube presenta algunas ventajas: el tamaño de la aplicación móvil va a ser menor ya que no incluye ningún archivo (modelo) en su código fuente y, además, en el caso de querer actualizar el modelo no es necesario generar una nueva versión de la aplicación con el modelo actualizado, ya que el mismo puede ser descargado desde internet.

Para cumplir con las actividades mencionadas la plataforma puede contener los siguientes componentes y sus respectivas conexiones:

Componentes de la plataforma

El flujo de trabajo y de datos en la arquitectura es el siguiente:
1. Primero se debe recolectar las imágenes a ser utilizadas para el entrenamiento.
2. Luego se deben etiquetar las imágenes utilizando el software LabelImg, el cual generará un archivo de mapeo .xml para cada una de ellas.
3. Una vez etiquetadas las imágenes, se las debe dividir en 2 conjuntos (entrenamiento y testing). Ambos conjuntos deben ser subidos a un repositorio de Github.
4. Un documento de Google Colab se va a encargar de realizar el aumento de las imágenes subidas a Github. Luego de ello, generará los archivos necesarios para efectuar el entrenamiento de la red, los cuales subirá a Github.
5. Un segundo documento de Colab, haciendo uso de los archivos generados en el punto anterior, va a realizar el entrenamiento de la red. Durante el entrenamiento se irán generando checkpoints, los cuales serán subidos automáticamente a Google Drive.
6. Un tercer documento de Colab va a obtener el checkpoint más reciente desde Google Drive y va a generar el modelo TFLite, el cual va a dejar disponible para su descarga en ese mismo servicio de almacenamiento.
7. La aplicación móvil va a realizar la descarga del modelo desde Google Drive. Una vez descargado, la aplicación va a estar lista para comenzar a detectar objetos en tiempo real a través de la cámara del teléfono.

A continuación describiremos paso a paso las distintas actividades de la plataforma, desde el armado del dataset de entrenamiento hasta el uso del modelo en la aplicación. En cada etapa explicaremos los componentes involucrados y el intercambio de información dentro de la misma.

ETAPA 1. Armado del dataset de entrenamiento

Armado del dataset de entrenamiento

Output: archivos train.record, test.record y label_map.pbtxt subidos al repositorio de GitHub.

La primera actividad de la plataforma contempla la obtención de las imágenes, su etiquetado, su aumento y la generación de los archivos requeridos por la actividad de entrenamiento.

Obtención de imágenes
Lo primero que debemos hacer es obtener las imágenes que van a ser utilizadas para el entrenamiento de la red. En lo posible deben ser imágenes con buena definición y en donde los objetos de interés se visualicen de forma clara. Es deseable no incluir imágenes que posean zoom, ruido, poca luminosidad, excesivo brillo, etc. ya que el aumento de imágenes se va a encargar de generar esas situaciones.
Antes de proceder a etiquetar las imágenes es conveniente redimensionarlas a un tamaño único, generalmente al tamaño de la imagen mas chica, para que ocupen menos espacio en el almacenamiento y para reducir la cantidad de parámetros y cómputo utilizado durante el entrenamiento de la red neuronal. En Windows podemos utilizar el software Image Resizer for Windows que permite seleccionar la totalidad de las imágenes y con pocos clicks redimensionarlas al tamaño elegido.

Etiquetado usando LabelImg

Etiquetado de las imágenes
Cuando se trabaja con imágenes y detección de objetos una de las maneras que tenemos de proveer datos etiquetados es a través de archivos de mapeo .xml. Entonces, la imagen servirá como dato de entrada, y el archivo .xml como resultado.
Para la generación de estos archivos se puede utilizar el software LabelImg, un anotador de imágenes gratuito, ligero y sencillo de utilizar que se encuentra disponible para Windows, Mac y Linux.

Luego de etiquetar las imágenes se las debe dividir en 2 carpetas (training y test). La primera se va a utilizar para el entrenamiento, y la segunda para ir evaluando la performance del entrenamiento de manera periódica, lo cual le va a permitir al algoritmo realizar los ajustes necesarios en la red con el fin de mejorar las predicciones. El porcentaje de distribución entre ambas carpetas suele ser de 80% para training y 20% para test, sin embargo el porcentaje queda a elección del programador, de acuerdo a sus preferencias o necesidades.
Luego de dividir los archivos se los debe almacenar en la nube, para ello se va
a hacer uso de Github. Este servicio provee repositorios gratuitos con un limite de 100MB por archivo subido y de 1GB como máximo (recomendado) por repositorio, lo cual es más que suficiente para nuestro uso.

Aumento de imágenes

Aumento de las imágenes
Lo que debemos hacer a continuación es ampliar el conjunto de imágenes etiquetadas. Para ello, vamos a utilizar la técnica de aumento, que nos permite generar nuevas imágenes a partir de las ya existentes. Esta tecnica es útil para evitar el overfitting del modelo.
El aumento genera imágenes realizando transformaciones a la imagen original. Es posible por ejemplo rotar, agregar zoom, cambiar los colores o la iluminación, agregar ruido, etc.

Este proceso de aumento lo vamos a realizar utilizando el servicio Google Colaboratory (Colab), el cual es un entorno gratuito de Jupyter Notebook 7.
Jupyter Notebook es una aplicación web de código libre que permite crear y
compartir documentos que poseen código. Cada documento está compuesto por celdas, las cuales pueden contener código o texto y su resultado (texto, gráficos, tablas,resultados de operaciones) se muestra luego de cada una de ellas. Al soportar Python es ampliamente utilizado en tareas de Machine Learning.
Google Colab no requiere configuración, se ejecuta completamente en la nube y provee en su versión gratuita una GPU K80, 12GB de memoria RAM y 12 horas de uso continuo hasta que se reinicie el entorno. Además, provee un filesystem, cuenta con librerías pre instaladas listas para ser utilizadas y permite conectarse a servicios como Github y Google Drive de manera sencilla.
Ejecutar documentos de Colab en la nube presenta varias ventajas. Una de ellas es que se hace uso del hardware de Google, lo cual garantiza una alta estabilidad y disponibilidad de los recursos. Otra ventaja es que permite que una persona que posea hardware no adecuado para entrenar modelos de Machine Learning, pueda hacerlo, ya que otorga un gran poder de cómputo de manera gratuita.

Ejemplo de uso de albumentations

La idea del documento de Colab es aumentar las imagenes utilizando la librería albumentations y generar, a partir de las imágenes originales, de las imágenes aumentadas y del comando generate_tfrecord.py, los archivos train.record, test.record y label_map.pbtxt, los cuales son requeridos por la red neuronal para realizar el entrenamiento. El archivo label_map.pbtxt es un archivo de texto en donde se especifica el ID y el nombre de los objetos etiquetados en la imagen.
Colab nos permite configurar variables en el documento, las cuales podríamos usar para especificar la cantidad de imágenes a generar, la URL del repositorio de Github donde se encuentran las imágenes y la URL donde se van a subir los archivos generados por esta actividad.
La ultima actividad del Colab es subir esos archivos generados a Github para que puedan ser descargados por la siguiente actividad.

ETAPA 2. Entrenamiento del modelo

Entrenamiento del modelo

Input: archivos train.record, test.record y label_map.pbtxt del repositorio de GitHub.
Output: checkpoints, subidos a Google Drive

Una vez que se subieron los archivos train.record, test.record y label_map.pbtxt a Github se puede hacer uso de un nuevo documento de Google Colab para entrenar el modelo.
Podríamos usar variables en Colab para por ejemplo especificar el número de etapas de entrenamiento y la dirección del repositorio de Github que contiene los archivos generados por la actividad anterior. Además, podríamos disponer de otra variable con la URL del modelo pre-entrenado a utilizar.
Para realizar el entrenamiento es necesario realizar algunas modificaciones en el archivo de configuración del modelo a reutilizar seleccionado. Este archivo puede ser descargado desde el repositorio de TensorFlow y posee toda la configuración a ser utilizada durante el entrenamiento. Como mínimo se deben modificar las rutas de los directorios donde se encuentran los archivos train.record, test.record y label_map.pbtxt, y además se debe modificar la cantidad de objetos a detectar.

Con Colab tambien podemos (mediante pocas líneas de código) sincronizar su filesystem a nuestro Google Drive, el cual va a servirnos como almacenamiento y backup del entrenamiento. Drive cuenta con una capacidad máxima (compartida con GMail y Google Photos) de 15GB para su versión gratuita, lo cual nos va a permitir trabajar sin inconvenientes.
Luego de sincronizar nuestro Drive, debemos descargar el modelo pre-entrenado que vamos a utilizar, y dar comienzo al entrenamiento, el cual se va a llevar a cabo utilizando la librería de código libre TensorFlow.

Predicciones en TensorBoard

Durante el entrenamiento se van a ir mostrando diferentes métricas. Si se desea visualizar un informe más detallado sobre el desempeño del modelo
durante el entrenamiento se puede utilizar la herramienta TensorBoard, la cual viene incluida en el framework TensorFlow. Esta herramienta permite no solo observar las métricas de loss y mAP, sino también una gran cantidad de métricas diferentes y además, las predicciones realizadas en las distintas etapas de entrenamiento.

Como comentamos anteriormente, el entrenamiento es un proceso iterativo y de prueba y error. Se debe ir observando los resultados parciales devueltos por TensorFlow (y por TensorBoard si es posible) para ir realizando ajustes en el caso que los resultados en las predicciones y en las diferentes métricas no cumpla con las expectativas.
A medida que transcurre el entrenamiento se generarán diferentes checkpoints, los cuales guardan el estado (variables, operaciones, pesos) que contiene la red neuronal en un determinado instante.
Al tener el filesystem de Colab sincronizado con Google Drive, los checkpoints serán salvados automaticamente en Drive, lo cual va a permitir generar el modelo TFLite y además, poder resumir el entrenamiento en caso que ocurra algún error.

Deploy del modelo TFLite

Deploy del modelo

Input: checkpoints en Google Drive.
Output: modelo .tflite subido a Google Drive.

Esta actividad tiene como objetivo generar el modelo TFLite a ser utilizado por la aplicación móvil.
En la aplicación vamos a utilizar la librería TensorFlow Lite para realizar la detección de objetos, la cual está diseñada para ejecutar modelos de manera eficiente en dispositivos que poseen recursos limitados. Parte de esa eficiencia proviene del uso del formato TFLite.
Los modelos generados por TensorFlow deben convertirse al formato TFLite para que TensorFlow Lite pueda hacer uso de ellos. Esta conversión reduce sustancialmente su tamaño e introduce optimizaciones que no afectan la precisión del mismo. Es posible, además, reducir aún más el tamaño del modelo y aumentar su velocidad de ejecución, a costa de alguna leve penalidad, como por ejemplo en su eficacia en la detección.

El objetivo del documento de Colab es descargar el checkpoint más reciente del entrenamiento y utilizar los scripts de TensorFlow: tflite_convert y export_tflite_ssd_graph para generar el modelo TFLite.
El script “tflite_convert” permite convertir el modelo al formato TFLite y opera con archivos con extensión “.pb”, por lo que primero se debe convertir el checkpoint a ese formato.
La extensión .pb refiere a “protobuf ”, un tipo de archivo utilizado por TensorFlow que contiene la definición del grafo de la red neuronal y los pesos del modelo.

Generación del modelo. pb

Para la generación del modelo .pb es necesario el script “export_tflite_ssd_graph”.

La ejecución del script “tflite_convert” dará como resultado el archivo “detect.tflite”, el cual debemos subir a Google Drive para su descarga desde la aplicación.
Para permitir que la aplicación pueda descargar un modelo y sus sucesivas actualizaciones utilizando la misma URL es necesario que la subida del archivo “detect.tflite” se realice siempre hacia la misma ubicación, con el objetivo de ir sobrescribiendo continuamente el mismo archivo. Eso permite, además, poder restaurar una versión anterior del modelo, en el caso que la nueva versión del modelo no sea tan efectiva como alguna anterior.

ETAPA 3. Inferencia, uso del modelo en la Aplicación Móvil

Uso del modelo en la APP

Input: modelo .tflite disponible en Google Drive

La última actividad de la plataforma es el uso, en la aplicación móvil, del modelo que hemos entrenado para detectar nuestros objetos.
En este caso disponemos de una Aplicacion Android, pero debemos tener en cuenta que los modelos TFLite pueden ser usados en iOS, en plataformas Linux (por ejemplo en Raspberry Pi) y en microcontroladores como Arduino.

App Android que detecta objetos en tiempo real

En la aplicación podemos disponer de ciertas variables, tales como el porcentaje mínimo de confianza que deben tener las predicciones a ser mostradas, el tamaño de la línea del bounding box y el ID del archivo del modelo .tflite que se encuentra en Google Drive, el cual va a servir para descargar el archivo al dispositivo.

Como ya mencionamos, vamos a hacer uso de la librería TensorFlow Lite. Luego de enlazar esa librería con el modelo descargado y de configurar el uso de la cámara trasera para que capture las imágenes, se comienza con el ciclo de detección, el cual sigue los siguientes pasos:

  1. Cada algunos milisegundos el sistema obtiene una nueva imagen desde la cámara e invoca a un callback para informar sobre la existencia de la misma. El callback invocado depende del hardware del teléfono celular. Si el hardware posee soporte total de la API de Camera2 se invoca al método
    public void onImageAvailable(final ImageReader reader)
    caso contrario se invoca al método
    public abstract void onPreviewFrame(byte[] data, Camera camera)
  2. Dentro del callback, se procesa la imagen y se le hacen ciertas transformaciones, entre las que se incluye la conversión a Bitmap para poder ser manejada por la librería de TensorFlow Lite. Luego se la envía al método
    List<Recognition> recognizeImage(Bitmap bitmap)
    de la clase Classifier, el cual recibe un Bitmap, ejecuta la detección de objetos sobre él y retorna un listado con los objetos detectados (de clase Recognition).
    La clase Recognition posee el id, nombre, nivel de confianza y cuadro delimitador de cada objeto detectado.
    Es importante aclarar que las clases Classifier y Recognition forman parte
    de la librería de TensorFlow Lite.
  3. Una vez que se devuelven los objetos detectados, es ideal desestimar los que no cumplan con un valor mínimo de confianza establecido por el usuario/programador.
    Luego debemos mostrar las detecciones al usuario y volver al Punto 1 para reiniciar el ciclo de detección.

Y … eso es todo!
La idea de este artículo no es profundizar sobre el campo de Machine Learning ya que existe amplia literatura sobre el mismo; por el contrario,
pretende facilitar esa primera aproximación hacia el tema, y lograr que se obtenga más rápidamente una visión general del proceso completo que abarca tanto el entrenamiento como uso de modelos de Machine Learning.

Espero que este artículo te haya resultado útil y que haya logrado aclararte algunas dudas (o todas).

Si queres contactarte conmigo, podes encontrarme en LinkedIn.

--

--