Classificação de dados de imagem com o BigQuery ML

1. Introdução

Neste codelab, vamos falar sobre o caso de uso de armazenamento e análise de imagens de posturas de ioga no BigQuery e implementação de um modelo de classificação com o BigQuery ML para rotular as posturas usando apenas construções SQL, sem qualquer outra forma de código.

BigQuery e BQML

O BigQuery é um data warehouse em nuvem sem servidor que consegue escalonar de bytes a petabytes sem sobrecarga operacional. Isso o torna uma ótima opção para armazenamento de dados de treinamento de ML. Além disso, o BigQuery Machine Learning integrado (BQML) e os recursos de análise permitem criar previsões sem código usando somente consultas SQL. É possível acessar dados de fontes externas com consultas federadas, o que elimina a necessidade de pipelines de ETL complicados. Leia mais sobre tudo o que o BigQuery pode oferecer nesta página.

Até agora, conhecemos o BigQuery como um data warehouse em nuvem totalmente gerenciado que ajuda os usuários a analisar dados estruturados e semiestruturados. Mas…

  • O BigQuery se expandiu para executar todas as análises e ML com dados não estruturados também
  • É possível usar consultas SQL para realizar análises criteriosas, estudos e ML de imagens, vídeos, áudio etc. na medida certa sem que você precise escrever um código adicional
  • Conseguimos combinar dados estruturados e não estruturados como se estivessem todos juntos em uma tabela

Vamos abordar isso no caso de uso de classificação das posturas de ioga tratado na próxima seção.

Classificação de dados de imagem com o BigQuery ML

A capacidade de processar e analisar imagens por consultas estruturadas como se fossem dados estruturados é a primeira desse tipo. Agora é possível prever resultados usando modelos de classificação de aprendizado de máquina pelo BigQuery ML. Eu reduzi as fases das 5 etapas para facilitar a compreensão:

fe97945bce996e1.jpeg

As etapas anteriores podem ficar complicadas se as analisarmos apenas como rótulos. Os detalhes de cada componente envolvido, como conjunto de dados do BigQuery, conexão do BigLake, buckets do Cloud Storage (contêineres), tabela de objetos (fonte de dados externa), BQML etc., estão definidos na seção de implementação. Portanto, não se desanime por ainda não conhecer esses termos.

O que você vai criar

Você vai criar um modelo de classificação de dados de imagem com o BQML e abordar o seguinte:

  • Um conjunto de dados do BigQuery para conter os componentes da tabela e do modelo
  • Bucket do Google Cloud Storage (GCS) para armazenar imagens de ioga para o modelo
  • Uma tabela externa para acessar imagens do Cloud Storage
  • Uma conexão do BigLake para a tabela externa acessar as imagens no GCS
  • Modelo ResNet no BigQuery ML
  • Inferência usando o modelo criado
  • BigQuery SQL para análise de dados de imagem
  • BigQuery SQL para consultar os dados estruturados e não estruturados juntos

O que você vai aprender

  • Como criar um bucket do Cloud Storage e armazenar imagens
  • Como criar um conjunto de dados, uma tabela e uma conexão do BigQuery
  • Como criar um modelo de classificação de dados de imagem usando o BQML
  • Como fazer previsões com o modelo criado usando o BigQuery ML
  • Como consultar imagens e combinar com dados estruturados usando SQLs do BigQuery

2. Requisitos

  • Um navegador, como o Chrome ou o Firefox
  • Um projeto do Google Cloud com faturamento ativado e que contenha os serviços do BigQuery, Cloud Storage e conexão do BigLake
  • A próxima seção mostra a lista de etapas para a criação do aplicativo de classificação de dados de imagem

3. Crie um conjunto de dados e uma conexão do BigLake

Para o caso de uso de detecção de imagem de 5 posturas de ioga, eu usei um conjunto de dados disponível publicamente. Você pode acessar o conjunto de dados por este repositório. As posturas de ioga que vamos identificar são apenas Cachorro olhando para baixo, Deusa, Prancha, Árvore e Guerreiro 2. Antes de começar a criar o conjunto de dados do BigQuery, selecione ou crie um projeto do Google Cloud e verifique se o faturamento está ativado nele. Ative a API BigQuery e a API BigQuery Connection. Todos os serviços usados nesta implementação devem ficar na mesma região escolhida.

a. Siga as etapas abaixo para criar um conjunto de dados "yoga_set":

Acesse o editor do BigQuery e digite o comando:

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

b. A conexão do BigLake permite conectar a fonte de dados externa, mantendo o controle de acesso e a segurança refinados do BigQuery, que, nesse caso, é o Cloud Storage para os dados de imagem. Vamos usar essa conexão para ler objetos do Cloud Storage. Siga as etapas abaixo para criar a conexão do BigLake.

Clique em "Adicionar dados" no painel Explorer da página do BigQuery:

4cb42b1245bb0ba6.pngTela "Adicionar dados externos" do BigQuery

Clique em Conexões com fontes de dados externa e selecione a opção BigLake e funções remotas:

9ffec2b2bfcc3cd5.pngConfigure a conexão da fonte de dados externa

Forneça o ID da conexão e crie a conexão. Anote o ID da conta de serviço que será exibido na tela assim que a conexão for criada <<SERVICE_ACCOUNT>>. No exemplo, o ID da conexão é "yoga-pose-conn". Não se esqueça de anotar a região.

4. Crie um bucket do Google Cloud Storage e conceda permissões

Usaremos o bucket do Google Cloud Storage para conter os arquivos de imagem das posturas de ioga que vão servir para a criação do modelo. Buckets são contêineres do Cloud Storage em que ficam as imagens que vamos analisar.

a. Pesquise pelo Google Cloud Storage no console para acessá-lo. Em seguida, clique em Buckets, para acessar a página inicial dos buckets, e depois em "Criar"

a6f6b26cffb53ae0.pngPágina "Buckets" do Google Cloud Storage

b. Na página "Criar um bucket", insira as informações do bucket (um nome exclusivo) e clique em "Continuar". O bucket deve ficar na mesma região que o conjunto de dados e a conexão, conforme discutido nas etapas anteriores. Em seguida, clique em "Criar"

1280366a42b7bdf6.pngPágina "Criar um bucket" do Google Cloud Storage

Antes de passar para a próxima etapa, verifique se você anotou a conta de serviço, o nome do bucket e o caminho.

c. Depois que o bucket for criado, armazene as imagens pelo console, por comandos do Cloud Shell ou de forma programática, e conceda as permissões necessárias para a conta de serviço da conexão, salva anteriormente, acessar as imagens

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

5. Crie uma tabela de objetos

Crie uma tabela de objetos externa do BigQuery para acessar os dados não estruturados do bucket usando a conexão que criamos. Execute CREATE SQL no editor do 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"]);

A tabela de objetos é criada conforme mostrado abaixo:

bda48f566e0c292f.png

Consulte rapidamente uma postura da tabela externa recém-criada:

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

Como a captura de tela abaixo mostra, é possível criar e operar imagens não estruturadas como se fossem dados estruturados:

7d1784122b5013f.png

Exporte o resultado da consulta para um pequeno snippet do Python para visualizá-lo:

Clique em "Salvar resultados" e selecione a opção "Arquivo local CSV" para exportar o resultado. Depois abra o notebook do Colab ou crie um e digite o código abaixo

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)

Execute-o para exibir o resultado abaixo:

b8edd68cb281786a.png

Depois de criarmos a tabela externa e acessarmos as imagens do Cloud Storage usando apenas consultas SQL, vamos para a próxima seção para criarmos o modelo de classificação.

6. Crie o modelo e faça o upload dele para o Google Cloud Storage

Para esta implementação, vamos usar o Modelo ResNet 50 pré-treinado para executar a inferência na tabela de objetos que criamos. O modelo ResNet 50 analisa arquivos de imagem e gera um lote de vetores que representa a probabilidade de uma imagem pertencer à classe correspondente (logits).

Antes de prosseguir com a próxima etapa, confira se você tem todas as permissões necessárias. Siga as etapas abaixo:

  1. Faça o download do modelo a partir deste local e salve-o em seu local
  2. Ele deve ser descompactado em save_model.pb e em uma pasta de variáveis
  3. Faça o upload do arquivo e da pasta para o bucket que criamos na seção anterior

2629ff3eda214946.pngBucket "yoga_images" do Google Cloud Storage com os arquivos do modelo ResNet enviados

Depois de concluir essa etapa, os arquivos relacionados ao modelo devem estar no mesmo bucket que as imagens, conforme mostrado acima.

7. Carregue o modelo no BQML e faça a inferência

Nesta etapa, vamos carregar o modelo no mesmo conjunto de dados do BigQuery da tabela externa que criamos anteriormente e vamos aplicá-lo às imagens armazenadas no Cloud Storage.

a. No BigQuery Editor, execute a seguinte instrução SQL

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

Depois que a execução é concluída, o que pode demorar um pouco dependendo do conjunto de dados, você vê o modelo listado na seção Conjunto de dados do BigQuery.

435fa0919aeb57a6.pngConjunto de dados do BigQuery listando o modelo criado

b. Inspecione o modelo para conferir os campos de entrada e saída.

Abra o conjunto de dados e clique no modelo "yoga_poses_resnet". Clique na guia "Esquema".

e88928764f10f6ff.pngGuia "Esquema" de definição do modelo do BigQuery

Na seção "Rótulos", o campo "activation_49", que representa o campo de saída, é exibido. Na seção "Recursos", "input_1", que representa o campo que deve ser inserido no modelo, é exibido. Mencione "input_1" na consulta de inferência (ou consulta de previsão) como o campo que será transmitido para os dados de teste.

c. Faça a inferência da postura de ioga

Use o modelo criado para classificar os dados de imagem de teste. Não se esqueça de identificar no Cloud Storage Bucket algumas imagens de teste (posturas de ioga) que entraram na tabela externa quando ela foi criada. Vamos consultar seletivamente essas imagens de teste no BigQuery para fazer a inferência usando o modelo do BQML que criamos. Use a consulta abaixo para acionar o teste.

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')));

Na consulta acima, você selecionou uma imagem de teste identificada para conter um valor de URI específico (00000097.jpg) na tabela externa. Além disso, a parte SELECT usa a construção ML.DECODE_IMAGE como campo "input_1" para que a função ML.PREDICT funcione.

Depois que a execução é concluída, você vê o resultado conforme mostrado abaixo:

867018993845e943.png

Para quem conhece bem o modelo ResNet, isso ajuda a entender a classificação. Caso contrário, codifique um pequeno snippet para entender a classificação visualmente.

d. Como nivelar o resultado

Uma maneira de visualizar a saída mostrada acima é nivelar os valores do campo activation_49 usando a construção UNNEST do BigQuery SQL. Confira a consulta abaixo para nivelar o resultado da etapa anterior. Se você quer rotular textualmente a classe resultante, é possível introduzir a lógica no lugar do marcador de posição <<LABEL_LOGIC>> na consulta. Remova a marca de comentário ao usá-la.

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;

Sem a lógica de rotulagem da classe, confira abaixo a saída da consulta:

71f580f41f0811f3.png

No meu caso, apliquei uma lógica de exemplo. Confira o resultado abaixo:

1c6df6ecd14fba1.png

Leia mais sobre o modelo e aplique a lógica que funciona melhor com seus dados e a saída do modelo.

e. Como visualizar a inferência

Finalmente, um snippet rápido do Python para visualização do resultado da classificação. Exporte o resultado da consulta para um arquivo CSV e mencione-o no código Python.

68756e7e4b8d7a29.png

A saída da imagem refere-se à postura de ioga "Cão olhando para baixo", que é a mesma entrada de teste transmitida à consulta ML.PREDICT para classificação usando o BQML.

8. Unifique dados estruturados e não estruturados

Por fim, minha parte favorita dessa implementação é unificar os campos da tabela relacional estruturada com esses dados de imagem não estruturados. Criei uma tabela estruturada do BigQuery no mesmo conjunto de dados da tabela externa para manter a postura e os respectivos dados relacionados à saúde.

125bdf848c86fbe.pngEsquema "yoga_health" da tabela estruturada do BigQuery

A imagem acima representa o esquema da tabela de dados estruturados denominada "yoga_health" e os campos são pose, focus, health_benefit e breath. A consulta abaixo une dados estruturados e não estruturados:

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)];

Confira o resultado:

469bdfcffa9e19fd.png

Observação: todas as consultas abordadas neste blog podem ser executadas diretamente do notebook do Python usando os comandos mágicos do BigQuery.

9. Limpeza

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados nesta postagem, execute as etapas a seguir.

  1. No console do Google Cloud, acesse a página Gerenciar recursos.
  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir.
  3. Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.

10. Parabéns

Parabéns! Você armazenou e consultou corretamente dados não estruturados no BigQuery, criou um modelo de classificação usando o BQML e previu posturas de ioga de teste com o modelo Se você gosta dessa implementação, comece com seu projeto do Google Cloud. Além disso, se você quiser saber mais sobre bancos de dados ou outras implementações completas de aplicativos no Google Cloud, acesse meus blogs.