Criando um modelo de classificação de imagens com AutoML na Vertex AI
* TLDR: Aqui vamos passar pelo processo de definição de um modelo de machine learning de classificação de imagens, com a facilidade que o Google AutoML oferece, utilizando a Vertex AI, plataforma de desenvolvimento de soluções de machine learning na Google Cloud.
Como chegamos até aqui?
No mês de abril, o time de Google Cloud Brasil publicou, em 5 (cinco) episódios, uma série técnica chamada “Desvendando AI”, toda em português e voltada para audiência de praticantes de tecnologia (engenheiros, desenvolvedores, pesquisadores, etc):
Se você ainda não viu, confere na playlist do canal Google Cloud LATAM.
Em um dos vídeos, recebi o comentário abaixo:
E aqui estamos. Vamos no passo a passo de como utilizar a Vertex AI para treinar um modelo de classificação de imagens em uma abordagem low code — Ou seja, utilizando o Google AutoML e sem necessitar criar cada etapa e cada detalhe do modelo de machine learning que será gerado.
Mas o que faremos aqui?
Para definirmos uma base do que faremos, vamos olhar o que envolve um processo de modelagem e treinamento de machine learning. O processo se inicia na análise de desafio de negócio, onde definimos qual problema precisa ser resolvido; passamos por uma análise de dados disponíveis, a modelagem em si (no framework que você escolher — TensorFlow, PyTorch, scikit-learn, etc), treinamento e otimização do modelo até chegar na avaliação e uso do modelo em si… E começamos tudo de novo, num ciclo iterativo e incremental. Algo como a figura abaixo:
Como o Google AutoML ajuda nesse processo? O AutoML irá abstrair pra você (ou realizar por você) as etapas de engenharia de features, definição de modelos a serem treinados, treinamento e otimização desses modelos, seleção do melhor modelo e disponibilização do modelo para você. Ou seja, as ações da imagem abaixo:
Ou seja, você consegue salvar tempo de prototipação, focando mais no problema que você quer resolver e na qualidade dos seus dados e o AutoML será responsável por selecionar o melhor modelo possível em seu universo de modelos possíveis (que inclui modelos criados pela engenharia do Google e variações de modelos utilizando Neural Architecture Search, ou NAS — mas este tópico merece uma postagem inteira dedicada a isso. Mas vamos as estapas do laboratório de Vertex AI com Google AutoML.
Definição dos dados a serem utilizados
Para realizar este experimento, vamos usar o dataset gratuito ImageNetDogs, criado e gerido pela universidade de Stanford. O dataset é composto de mais de 20.000 (vinte mil) imagens de 120 (cento e vinte) raças de cachorros. São todas imagens reais, sem muita produção (não são imagens de estúdio, ou com cores e brilho otimizados), buscando montar algo que seja o mais próximo possível de fotos do nosso cotidiano (que fotografaríamos de nossos cachorros com nossos celulares). Um exemplo abaixo:
Como o dataset é bem grande, ele acaba aumentando a complexidade desse laboratório experimentativo; além disso, o AutoML realiza ações de aumento do dataset (dataset augmentation) o que nos permite criar datasets menores. Então, antes de começarmos, podemos criar um “sub-dataset” contendo menos raças de cachorros (apenas 15, das 120) e com menos exemplos de imagens de cada raça (100 imagens por raça). Para isso, usamos o shell script abaixo:
$ mkdir dataset
$ cd dataset; axel -n 15
$ tar -xf images.tar
$ cd Images; for dir in `ls`; do new_name=`echo $dir | cut -d- -f2-`; mv $ dir $new_name; done;
$ for dir in `find . -type d | shuf -n 15`; do dirname=`echo $dir | cut -d/ -f2`; mkdir -p ../train/$dirname; for img in `find $dir -type f | shuf -n 100`; do mv $img ../train/$dirname; done; done
Com isso, criamos uma estrutura de diretórios contendo 15 (quinze) pastas com nomes de raças de cachorro e 100 (cem) imagens de cada raça dentro dos diretórios correspondentes de cada raça. O próximo passo é de copiar as imagens para um Cloud Storage bucket. Neste cenário, criei um bucket chamado gs://vertexai-labs. É importante alterar o comando abaixo de acordo com as configurações de seu ambiente:
$ gsutil -m cp -r dataset/train/* gs://vertexai-labs/cachorros-dataset
Para que as imagens sejam incluídas na Vertex AI, precisamos criar um arquivo .csv que contenha a lista de todas as imagens que serão utilizadas para compor o dataset de treinamento. Maiores detalhes sobre este processo de definição do dataset podem ser encontrados na documentação da Vertex AI. Para criar o arquivo CSV com a lista de imagem, utilizamos o comando abaixo:
$ for img in `cat dataset/list.out`; do classe=`echo $img | cut -d/ -f5`; echo "${img},${classe}" >> dataset/dataset.csv; done
$ gsutil -q cp dataset/dataset.csv gs://vertexai-labs/cachorros-dataset
Com todos os dados necessários armazenados no bucket do Cloud Storage, agora faremos a criação do dataset gerenciado na Vertex AI. Utilizaremos a SDK de Python no processo.
Primeiro iremos importar o módulo Python de desenvolvimento com a Vertex AI, depois instanciar um cliente da Vertex AI e, finalmente, criar o dataset gerenciado e popular com os dados do bucket do Cloud Storage. Algo mais ou menos assim:
import google.cloud.aiplatform as aiplatform
from google.cloud.aiplatform import ImageDataset, schema
# definindo as variáveis necessáris
projeto='lucianomartins-demos-345000'
regiao='us-central1'
bucket='gs://vertexai-labs'
schema_uri = schema.dataset.ioformat.image.single_label_classification
# instanciando o cliente da Vertex AI
aiplatform.init(project=projeto,
location=regiao,
staging_bucket=bucket)
# criando o dataset gerenciado
dataset = ImageDataset.create(display_name='cachorros-dataset',
sync=True)
# populando o dataset com as imagens do bucket
dataset = dataset.import_data(gcs_source=bucket + \
'/cachorros-dataset/dataset.csv',
import_schema_uri=schema_uri,
sync=True,
import_request_timeout=2700.0)
O processo de importação das imagens pode demorar alguns minutos (cerca de quinze minutos). Ao final desta etapa, você terá o seu dataset gerenciado criado — e que pode ser visto na console da Vertex AI):
Criando o job de treinamento da Vertex AI com Google AutoML
Com o dataset preparado, a próxima etapa é realizar o treinamento de um modelo com AutoML. Por ser uma abordagem low code, ou seja, que não é necessário desenvolver, explicitamente, todas os detalhes do modelo de machine learning, teremos somente duas ações para tomar: a definição do job de treinamento e a execução do job de treinamento.
Para criar o job de treinamento, utilizaremos o cliente da Vertex AI, da SDK de Python, como fizemos para a criação do dataset gerenciado.
Vale uma explicação das informações que estamos informando:
“display name” é como ficará a descrição do job na Vertex AI
“prediction type” é qual cenário de visão computacional estamos trabalhando (classificação de imagens, neste caso)
Se o cenário é uma classificação “multi_label”, ou seja, se em uma mesma imagem pode haver várias classes (ou raças) possíveis. No nosso caso, não
“model_type”, para definir se o modelo será utilizado na Google Cloud ou preparado para ser utilizado na “borda”, em um cenário de IoT. Aqui utilizamos a opção de para “cloud”
E finalmente, informamos que não estamos otimizando um modelo treinado previamente com “base_model=None”.
job = aiplatform.AutoMLImageTrainingJob(
display_name='treinamento de classificador de cachorros',
prediction_type='classification',
multi_label=False,
model_type='CLOUD',
base_model=None)
Tendo a definição do job, podemos executá-lo (também utilizando a SDK da Vertex AI). Aqui informamos:
qual dataset será utilizado; o “model_display_name”, que é a descrição do modelo na Model Registry (ou biblioteca de modelos treinados)
como o nosso dataset será utilizado (aqui teremos 80% das imagens para o treinamento do modelo, 10% para a avaliação do modelo durante o treinamento e 10% para testes após o treinamento)
Além de outros detalhes de execução (para ver todas as possibilidades, verifique a documentação da Vertex AI para execução de jobs de treinamento):
model = job.run(
dataset=dataset,
model_display_name='classificador-cachorros',
training_fraction_split=0.8,
validation_fraction_split=0.1,
test_fraction_split=0.1,
budget_milli_node_hours=10000,
disable_early_stopping=False)
Esse processo pode demorar um tempo — No meu lab aqui, levou, mais ou menos, 2 horas e 30 minutos pra ser finalizado. Com o processo finalizado, podemos verificar as métricas do treinamento via a a console da Vertex AI e via a SDK da Vertex AI. Aqui como estamos fazendo tudo via SDK, vamos seguir nessa abordagem:
model_evaluations = model.list_model_evaluations()
for model_evaluation in model_evaluations:
print(model_evaluation.to_dict())
O resultado é a lista de todas as informações referentes às métricas do treinamento — coisas como acurácia, precisão, recall, a matriz de confusão, etc (deixando aqui só um pedaço da saída do comando):
{'name': 'projects/48397268769/locations/us-central1/models/4167564684666339328@1/evaluations/5273414928256991232', 'metricsSchemaUri':
<…>
'confidenceMetrics': [{'confidenceThreshold': 0.8, 'recall': 0.94666666, 'precision': 0.9726027},
<…>
Neste ponto, estamos prontos para o próximo passo — Implantar o modelo em uma API para usar o modelo de verdade.
Implantando o modelo treinado em uma API na cloud
Com as facilidades que a Vertex AI oferece, a implantação do modelo AutoML em uma API se baseia na execução de um único comando:
endpoint = model.deploy()
Após alguns minutos, a API estará disponível para receber chamadas REST e realizar inferências no seu modelo recém treinado.
Realizando inferências com a API do modelo
Para realizar a inferência, iremos utilizar uma imagem do dataset de Stanford que não foi utilizada no processo de treinamento. É importante que seja uma imagem não vista pelo modelo, para que o modelo não utilize o conhecimento que ele já possui sobre a imagem e acabe acertando a inferência porque “decorou” a informação.
Iremos utilizar a imagem deste basset como teste:
Para realizar a inferência devemos:
Transformar a imagem em formato `base64`
Realizar a chamada REST na API que implantamos
Tratar os resultados da inferência.
Algo como abaixo — primeiro transformando a imagem em formato base64:
with open('./imgs/testimg.jpg', 'rb') as image_file:
imagem = base64.b64encode(image_file.read())
Após isso, vamos utilizar a SDK da Vertex AI e enviar a chamada REST de inferência:
instances = [{"content": imagem.decode("utf-8")}]
prediction = endpoint.predict(instances=instances)
E, finalmente, realizar o processamento da resposta da inferência (armazenada na variável "prediction"):
id_raca = prediction[0][0]['confidences']
id_raca = id_raca.index(max(prediction[0][0]['confidences']))
prediction[0][0]['displayNames'][id_raca]
'basset'
Parabéns!! chegando até aqui você:
criou um dataset gerenciado na Vertex AI
treinou um modelo de machine learning, em uma abordagem low code, utilizando o AutoML
fez a implantação desse modelo em uma API
realizou inferências com esse modelo
Você gostou do conteúdo e quer replicar o código em seu ambiente? Sem problemas!! Basta seguir as etapas presentes neste repositório no github.
Um abraço e até a próxima!