Clasificación de datos de imágenes con BigQuery ML

1. Introducción

En este codelab, analizaremos el caso de uso de almacenar y analizar imágenes de posturas de yoga en BigQuery y de implementar un modelo de clasificación con BigQuery ML para etiquetar las posturas solo con construcciones en SQL y ninguna otra forma de código.

BigQuery y BQML

BigQuery es un almacén de datos sin servidores y de múltiples nubes que puede escalar de bytes a petabytes sin nada de sobrecarga operativa. Esto lo hace una excelente opción para almacenar datos de entrenamiento de AA. Además, el aprendizaje automático de BigQuery (BQML) integrado y las capacidades analíticas te permiten crear predicciones sin código solo con consultas en SQL. Además, puedes acceder a datos de fuentes externas con consultas federadas, lo que elimina la necesidad de tener canalizaciones complejas de ETL. Puedes leer más sobre todo lo que te puede ofrecer BigQuery en la página de BigQuery.

Hasta ahora, sabemos que BigQuery es un almacén de datos en la nube completamente administrado que ayuda a los usuarios a analizar datos estructurados y semiestructurados. Sin embargo,

  • BigQuery se expandió para realizar todo el trabajo de análisis y AA también en datos no estructurados.
  • Podemos usar las consultas en SQL para realizar análisis útiles y generar estadísticas y AA a partir de imágenes, videos, audio, etc., a gran escala y sin tener que escribir más código.
  • Tenemos la capacidad de combinar datos estructurados y no estructurados como si existieran juntos en una tabla.

Analizaremos estas capacidades en nuestro caso de uso de clasificación de posturas de yoga de la próxima sección.

Clasificación de datos de imágenes con BigQuery ML

Tener la capacidad de procesar y analizar imágenes con consultas estructuradas como si fueran datos estructurados es de vanguardia. Ahora podemos incluso predecir resultados con modelos de clasificación de aprendizaje automático con BigQuery ML. Distribuí las etapas implicadas en 5 pasos para que se entiendan mejor:

fe97945bce996e1.jpeg

Estos pasos podrían ser complicados si solo los viéramos como etiquetas. Los detalles de cada componente implicado, como BigQuery Dataset, BigLake Connection, Buckets de Cloud Storage (contenedores), Tabla de objetos (fuente de datos externa), BQML, etc., se definen en la sección de implementación. Así que no te preocupes si todavía no conoces estos términos.

Qué compilarás

Crearás un modelo de clasificación de datos de imágenes con BQML que incluirá lo siguiente:

  • Un conjunto de datos de BigQuery que contenga los componentes de la tabla y del modelo
  • Un bucket de Google Cloud Storage (GCS) que almacene imágenes de yoga para el modelo
  • Una tabla externa para acceder a imágenes de Cloud Storage
  • Una conexión de BigLake para que la tabla externa acceda a las imágenes de GCS
  • El modelo ResNet en BigQuery ML
  • Inferencia con el modelo creado
  • BigQuery SQL para analizar datos de imágenes
  • BigQuery SQL para consultar los datos estructurados y no estructurados juntos

Qué aprenderás

  • Cómo crear un bucket de Cloud Storage y almacenar imágenes
  • Cómo crear un conjunto de datos, una tabla y una conexión de BigQuery
  • Cómo crear un modelo de clasificación de datos de imágenes con BQML
  • Cómo realizar predicciones con el modelo creado con BigQuery ML
  • Cómo consultar imágenes y combinarlas con datos estructurados usando SQL de BigQuery

2. Requisitos

  • Un navegador, como Chrome o Firefox
  • Un proyecto de Google Cloud con facturación habilitada que contenga tus servicios de BigQuery, Cloud Storage y BigLake Connection
  • En la siguiente sección se encuentra la lista de los pasos para crear la app de clasificación de datos de imágenes

3. Crea el conjunto de datos y una conexión de BigLake

Para nuestro caso de uso de detección de 5 posturas de yoga en imágenes, usé conjuntos de datos disponibles de manera pública. Puedes acceder a este conjunto de datos en este repositorio. Las posturas de yoga que vamos a identificar se limitan a la postura del perro boca abajo, la diosa, la plancha, el árbol y el guerrero 2. Antes de comenzar con la creación del conjunto de datos de BigQuery, asegúrate de seleccionar o crear un proyecto de Google Cloud y verifica que la facturación esté habilitada en el proyecto. Habilita la API de BigQuery y la API de BigQuery Connection. Ten en cuenta que todos los servicios usados en esta implementación deberían estar en la misma región que elijas.

a. Crea el conjunto de datos “yoga_set” con los pasos que se indican a continuación:

Dirígete a BigQuery Editor y escribe este comando:

CREATE SCHEMA `<<project_id>>.yoga_set`;

b. BigLake Connection nos permite conectar la fuente de datos externa y mantener el control de acceso y la seguridad precisos de BigQuery, lo que es nuestro caso es el almacén de Cloud Storage de los datos de imágenes. Usaremos esta conexión para leer objetos de Cloud Storage. Sigue estos pasos para crear la conexión de BigLake.

Haz clic en AGREGAR DATOS (ADD DATA) en el panel Explorador de la página BigQuery:

4cb42b1245bb0ba6.pngPantalla “Agregar datos externos” de BigQuery

Haz clic en Conexiones a fuentes de datos externas y selecciona la opción BigLake y funciones remotas (BigLake and remote functions):

9ffec2b2bfcc3cd5.pngConfigura la conexión de la fuente de datos externa

Proporciona el ID de conexión y crea la conexión. Recuerda anotar el ID de la cuenta de servicio que aparecerá en la pantalla cuando se cree la conexión <<SERVICE_ACCOUNT>>. En nuestro ejemplo, el ID de la conexión es “yoga-pose-conn”. No olvides anotar la región.

4. Crea el bucket de Google Cloud Storage y otorga los permisos

Vamos a usar el bucket de Google Cloud Storage para que contenga los archivos de imágenes de posturas de yoga a partir de las cuales queremos crear el modelo. Los buckets son contenedores de Cloud Storage que contienen las imágenes que vamos a analizar.

a. Dirígete a Google Cloud Storage. Para hacerlo, búscalo en la consola, luego, haz clic en Buckets para ir a la página principal de Buckets y, luego, haz clic en CREAR (CREATE).

a6f6b26cffb53ae0.pngPágina de buckets de Google Cloud Storage

b. En la página Crea un bucket (Create a bucket), ingresa la información de tu bucket (un nombre único) y continúa. Asegúrate de que esté en la misma región que el conjunto de datos y la conexión que mencionamos antes y haz clic en Crear.

1280366a42b7bdf6.pngPágina Crea un bucket de Google Cloud Storage

Antes de avanzar al siguiente paso, asegúrate de haber anotado tu cuenta de servicio, el nombre de tu bucket y la ruta de acceso.

c. Cuando hayas creado el bucket, almacena tus imágenes (mediante comandos de la consola o de Cloud Shell, o bien de manera programática) y otorga los permisos necesarios para la cuenta de servicio de la conexión (que guardamos antes) para acceder a las imágenes.

> export sa=<<"SERVICE_ACCOUNT">>
> gsutil iam ch serviceAccount:$sa:objectViewer "gs://<<bucket>>"

5. Crea una tabla de objetos

Crea una tabla de objetos externa desde BigQuery para acceder a los datos no estructurados en el bucket usando la conexión que creamos. Ejecuta el siguiente código CREATE en SQL en el editor de BigQuery:

CREATE OR REPLACE EXTERNAL TABLE `<<dataset>>.<<table_name>>`
WITH CONNECTION `us.<<connection-name>>`
OPTIONS(
object_metadata="SIMPLE", uris=["gs://<<bucket>>/<<folder_if_exists>>/*.jpg"]);

La tabla externa se creará como aparece a continuación:

bda48f566e0c292f.png

Consultemos rápidamente una postura en la tabla externa que acabamos de crear:

SELECT data , uri
FROM `yoga_set.yoga_poses`
WHERE REGEXP_CONTAINS(uri, 'gs://yoga_images/Downdog')
Limit 1;

Como puedes ver en la siguiente captura de pantalla, puedes crear y operar en imágenes no estructuradas como si fueran datos estructurados:

7d1784122b5013f.png

Ahora, exportemos el resultado de la consulta anterior a un fragmento pequeño de Python para ver el resultado:

Haz clic en GUARDAR RESULTADOS (SAVE RESULTS) y selecciona la opción “CSV Localfile” para exportar el resultado. Luego, abre tu notebook de Colab (o crea uno) y escribe el siguiente código:

from IPython.display import display
from PIL import Image
import io
import pandas as pd
import base64
df = pd.read_csv('/content/sample_data/<<your_csv>>')
imgdata = base64.b64decode(str(df.data[0]))
image = Image.open(io.BytesIO(imgdata))
display(image)

Ejecútalo para ver el resultado como se muestra a continuación:

b8edd68cb281786a.png

Ahora que creamos la tabla externa y accedimos a las imágenes de Cloud Storage utilizando solo consultas en SQL, avancemos a la siguiente sección en la que crearemos el modelo de clasificación.

6. Crea el modelo y súbelo a Google Cloud Storage

En esta implementación, vamos a usar el modelo ResNet 50 previamente entrenado para ejecutar inferencias en la tabla de objetos que acabamos de crear. El modelo ResNet 50 analiza los archivos de imágenes y genera un lote de vectores que representan la probabilidad de que una imagen pertenezca a la clase correspondiente (logits).

Antes de avanzar a este paso, asegúrate de tener todos los permisos necesarios. Luego, sigue estos pasos:

  1. Descarga el modelo de esta ubicación y guárdalo en tu ubicación local.
  2. Debería extraerse en saved_model.pb y una carpeta de variables.
  3. Sube el archivo y la carpeta al bucket que creamos en la sección anterior.

2629ff3eda214946.pngBucket de Google Cloud Storage “yoga_images” con los archivos del modelo ResNet Model cargados

Cuando completes este paso, los archivos relacionados con tu modelo deberían estar presentes en el mismo bucket que tus imágenes, como se muestra en la imagen anterior.

7. Carga el modelo en BQML y realiza la inferencia

En este paso, vamos a cargar el modelo en el mismo conjunto de datos de BigQuery que la tabla externa que creamos anteriormente y lo aplicaremos a las imágenes que almacenamos en Cloud Storage.

a. En BigQuery Editor, ejecuta la siguiente instrucción de SQL:

CREATE MODEL `<<Dataset>>.<<Model_Name>>`
OPTIONS(
model_type = 'TENSORFLOW',
model_path = 'gs://<<Bucket>>/*');

Cuando la ejecución se complete (lo que podría tardarse según tu conjunto de datos), verás el modelo en la sección del conjunto de datos en BigQuery.

435fa0919aeb57a6.pngConjunto de datos de BigQuery con el modelo creado

b. Inspecciona el modelo para ver sus campos de entrada y salida.

Expande el conjunto de datos y haz clic en el modelo “yoga_poses_resnet” que acabamos de crear. Haz clic en la pestaña Esquema (Schema):

e88928764f10f6ff.pngPestaña Esquema de la definición del modelo de BigQuery

En la sección Etiquetas (Labels), verás el campo “activation_49” que representa el campo de salida. En la sección Funciones (Features), podrás ver “input_1” que representa el campo que se espera que se ingrese al modelo. Usarás “input_1” como referencia en tu consulta de inferencia (o consulta de predicción) como el campo que estás pasando para los datos de tu “prueba”.

c. Infiere tu postura de yoga

Usemos el modelo que acabamos de crear para clasificar nuestros datos de imágenes de prueba. Asegúrate de tener algunas imágenes de prueba (posturas de yoga) identificadas de tu bucket de Cloud Storage que lograron estar en la tabla externa cuando la creamos. Vamos a realizar consultas de forma selectiva para aquellas imágenes de prueba que están en BigQuery para realizar la inferencia con el modelo BQML que acabamos de crear. Usa la siguiente consulta para activar la prueba.

SELECT *
FROM ML.PREDICT(
MODEL yoga_set.yoga_poses_resnet,
(SELECT uri, ML.DECODE_IMAGE(data) AS input_1
FROM yoga_set.yoga_poses where REGEXP_CONTAINS(uri,
'gs://yoga_images/Downdog/00000097.jpg')));

En la consulta anterior, seleccionamos una imagen de prueba que se identifica para que contenga un valor de URI específico (00000097.jpg) en la tabla externa. Además, la parte SELECT usa la construcción ML.DECODE_IMAGE como campo “input_1” para que la función ML.PREDICT se ejecute correctamente.

Cuando se complete la ejecución, verás el resultado como aparece a continuación:

867018993845e943.png

Si conoces el modelo ResNet en detalle, esto te debería ayudar a comprender la clasificación. De lo contrario, codifiquemos un fragmento pequeño para comprender de forma visual la clasificación.

d. Compacta el resultado

Una forma de visualizar el resultado anterior es compactar los valores del campo activation_49 con la construcción UNNEST de BigQuery SQL. Ve la siguiente consulta para compactar el resultado del paso anterior. Si quieres etiquetar aún más de forma textual la clase resultante, puedes ingresar la lógica en el lugar del marcador de posición <<LABEL_LOGIC>> en la consulta (quita el comentario cuando uses esto).

with predictions as (
SELECT
Uri, data, SPLIT(uri, "/")[OFFSET(ARRAY_LENGTH(SPLIT(uri, "/")) - 1)] as img,
i as label_i,
<<LABEL_LOGIC>> label,
Score
FROM ML.PREDICT(
MODEL yoga_set.yoga_poses_resnet,
(SELECT data, uri, ML.DECODE_IMAGE(data) AS input_1
FROM yoga_set.yoga_poses
WHERE
REGEXP_CONTAINS(uri,'gs://yoga_images/Goddess/00000007.jpg'))),
UNNEST(activation_49) as score WITH OFFSET i)
SELECT * FROM predictions
ORDER BY score DESC
LIMIT  5;

Sin la lógica de etiquetado de clase, a continuación aparece el resultado de la consulta:

71f580f41f0811f3.png

Sin embargo, en mi caso, apliqué una lógica de muestra y el siguiente es el resultado:

1c6df6ecd14fba1.png

Puedes leer más sobre el modelo y aplicar la lógica que funcione mejor con tus datos y el resultado del modelo.

e. Visualiza la inferencia

Por último, un breve fragmento de Python para visualizar el resultado de la clasificación. Exporta el resultado de la consulta anterior a un archivo CSV y úsalo como referencia en el código de Python.

68756e7e4b8d7a29.png

El resultado de la imagen anterior hace referencia a la postura de yoga “perro boca abajo”, que es la misma entrada de prueba que pasamos a la consulta ML.PREDICT para la clasificación con BQML.

8. Unifica datos estructurados y no estructurados

Por último, mi parte favorita de esta implementación es unificar los campos de mi tabla relacional estructurada con estos datos de imágenes no estructurados. Creé una tabla de BigQuery estructurada en el mismo conjunto de datos que la tabla externa para mantener la postura y sus datos relacionados con la salud.

125bdf848c86fbe.pngEsquema “yoga_health” de la tabla estructurada de BigQuery

La imagen anterior representa el esquema de la tabla de datos estructurados llamada “yoga_health” y los campos son pose (postura), focus (enfoque), health_benefit (beneficio_salud) y breath (respiración). La siguiente consulta une los datos estructurados y no estructurados:

SELECT SPLIT(uri, "/")[OFFSET(ARRAY_LENGTH(SPLIT(uri, "/")) - 2)] as pose,
a.health_benefit, breath, focus, data
FROM `abis-345004.yoga_set.yoga_health` a, yoga_set.yoga_poses b
WHERE a.pose = SPLIT(uri, "/")[OFFSET(ARRAY_LENGTH(SPLIT(uri, "/")) - 2)];

El resultado aparece a continuación:

469bdfcffa9e19fd.png

Nota: Todas las consultas que abordamos en este blog se pueden ejecutar directamente en tu notebook de Python con los comandos de BigQuery Magic.

9. Realiza una limpieza

Sigue estos pasos para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos que usaste en esta publicación.

  1. En la consola de Google Cloud, ve a la página Administrar recursos.
  2. En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrarlo.

10. Felicitaciones

¡Felicitaciones! Almacenaste, consultaste datos no estructurados en BigQuery, creaste un modelo de clasificación con BQML y predijiste posturas de yoga de prueba con el modelo, todo de forma correcta. Si quieres implementar todo esto, comienza con tu proyecto de Google Cloud. Además, si quieres obtener más información sobre las bases de datos, o bien otras implementaciones de aplicaciones de extremo a extremo en Google Cloud, consulta mis blogs.