Docker, deploy de modelos e Ciência dos Dados - parte 0/3: do ciclo de vida de desenvolvimento de software ao de Engenharia de Machine Learning
Metodologias e processos por trás da implementação de modelos em produção.
Quando escutei pela primeira vez sobre “containers” e “docker” eu fiquei meio assustado sem entender quase nada e pensei comigo mesmo: pra quê isso tudo serve? Por que a galera fala disso?
A situação piorava quando ouvia “dockerizar a API”, “containerizar o algoritmo treinado” 😣.
Consequentemente, uma das principais questões foi acerca da real utilidade dos containers no campo da Ciência dos Dados, utilidade essa que era um pouco obscura para mim.
Contudo, não encontrei, na época, conteúdos com uma explicação mais simples e com foco numa abordagem mais prática da ferramenta de maneira que eu pudesse formar o imaginário de como utilizar isso tudo.
Dessa forma, à medida que venho estudando e utilizando profissionalmente um pouco do Docker no mundo da Ciência dos Dados, decidi compartilhar um pouco desse aprendizado para que de alguma forma possa auxiliar aqueles que também estão no início do aprendizado no mundo da Ciência dos Dados.
Assim, veremos esses conceitos juntamente com o desenvolvimento de uma API para um modelo simples de diagnóstico de doenças cardiovasculares e, em seguida, iremos colocá-la em um container usando o Docker. Além de aprendermos como realizar essa implementação, veremos também a real utilidade de se fazer isso e quais benefícios trazem para um projeto de desenvolvendo de soluções de Machine Learning.
Contudo, antes colocarmos a “mão na massa”, eu gostaria de passar por alguns conceitos de desenvolvimento de software e deploy de aplicações, pois, à medida que os conhecemos, podemos juntar melhor as peças desse complexo quebra-cabeças do deployment de modelos e, também, adaptar as metodologias e práticas aos nossos contextos. Vamos lá?
Buscando ser mais explicativo, embora não tanto quanto eu gostaria e conseguiria, dividi nossa conversa em quatro postagens, sendo eles:
0) Docker, deploy de modelos e Ciência dos Dados — parte 0/3: do ciclo de vida de desenvolvimento de software ao de Engenharia de Machine Learning (você está aqui)
1) Docker, deploy de modelos e Ciência dos Dados - parte 1/3: Servindo nosso modelo com Paython e Flask (link)
2) Docker, deploy de modelos e Ciência dos Dados — parte 2/3: O que são containers e como ‘dockerizar’ nossa Flask API (você está aqui)
3) Docker, deploy de modelos e Ciência dos Dados — parte 3/3: deploy rápido e fácil do nosso container no Heroku! (ainda a produzir)
Sumário:
0) Link do Repositório
1) Introdução
2) O deploy e o ciclo de desenvolvimento de software
3) O deploy e o ciclo de vida da Engenharia de Machine Learning
4) O contexto de negócio que usaremos nas postagens seguintes dessa série
5) Resumindo a solução que iremos desenvolver
6) Conclusão
7) Referências
0) Link do Repositório
Toda a solução que desenvolveremos na série das três postagens seguintes estará disponível nesse repositório no github.
1) Introdução
Na área de desenvolvimento de software, em geral, chega um momento em que é preciso disponibilizar o produto para o cliente ou demais interessados, seja quando ele já está pronto, seja no meio do projeto, para fins de teste/feedback e validação de hipóteses de negócio. O ciclo de um projeto de Machine Learning não é tão diferente.
Se você está aqui, provavelmente já está familiarizado com os processos de extração de dados, análise exploratória, feature engineering e treinamento de algoritmos e provavelmente deve saber que, em muitos casos, o modelo precisa ser disponibilizado para o uso, já que no final das contas é pra isso que ele serve. É nesse momento que entra a ideia de “deploy”.
Veremos então um pouco do processo de desenvolvimento de software e o que esse tal “deploy’ realmente é para que, em seguida, possamos partir para um melhor entendimento do seu uso em Machine Learning.
2) O deploy e o ciclo de vida de desenvolvimento de software
Embora o ciclo de vida de um projeto de Machine Learning seja diferente do de desenvolvimento de softwares em geral, considero pertinente vermos um pouco desse último apenas para termos uma ideia geral dos conceitos e práticas dessa área que fazemos uso em ML.
De forma bem simples, “deploy” significar disponibilizar uma aplicação (em algum lugar) para que seja utilizada. O momento, no cronograma do projeto, que essa aplicação será disponibilizada dependerá muito do projeto em si, da empresa, do contexto, e dos objetivos de negócio.
Nesse campo, há diversos modelos de desenvolvimento de software. Conforme Sommerville (2018), esses modelos são representações simplificadas desse processo, e, assim, são também chamados de modelos genéricos. Contudo, “podem ser utilizados para explicar as diferentes abordagens ao desenvolvimento de software” (p. 31). A partir deles, é possível criar processos mais específicos para algum determinado contexto.
Mas o que nos interessa aqui são as etapas que, no geral, estão em todos esses modelos e, como veremos mais adiante, se assemelha muito com o ciclo de vida de um projeto de Engenharia Machine Learning.
Essas etapas são:
- Planejamento: identificar e deixar explícito os objetivos, calcular custos, cronograma, definir os times e a liderança.
- Definir os requisitos: na prática, poderia ainda estar no âmbito do planejamento. Basicamente, definir tanto o que o produto final será capaz de fazer quanto os requerimentos para que isso aconteça, como os recursos necessários. Para saber se essa entrega será realmente feita, é necessário definir as métricas de avaliação do produto, para que sejam acompanhadas tanto durante, quanto após do desenvolvimento.
- Design: definir como o software funcionará. E ai entram vários elementos: design gráfico, segurança, estrutura e etc.
- Desenvolvimento: é nessa etapa em que o produto em si é desenvolvido. Embora seja “onde a coisa é construída”, temos que lembrar a extrema importância das etapas anteriores de forma que é ela quem definirá a eficiente dessa etapa de desenvolvimento.
- Testes: é aquele momento de certificar de que a aplicação está funcionando como definido para que, assim, possa ser disponibilizada aos usuários. O nome no plural, “testes”, já nos indica que aqui são vários: estabilidade, segurança, entregar o que foi definido, e etc.
- Implementação (deploy): aqui entra a parte que nos interessa. Como já falamos, é deixar disponível para usuários. A forma com que isso acontece dependerá muito da natureza do software. E aqui um ponto importante são os ambientes em nuvem, que facilitam bastante a implementação, tanto em segurança, quanto em velocidade.
- Manutenção: monitorar o funcionamento e operacionalizar as alterações (como novas versões) que forem surgindo.
Em geral, a diferença entre os modelos e as aplicações práticas estão na dinâmica entre essas etapas, quando avançar, quando realizá-las concomitantemente, subdividi-las e etc.
Vamos discutir um pouco mais sobre a etapa de deploy.
Geralmente, o deploy da aplicação é feita em um determinado ambiente, ou seja, os ambientes de deploy (deployment environments). Esses ambientes estão representados, de forma simples, na figura a seguir.
- Local e Desenvolvimento: Em muitas situações o ambiente Local e o de Desenvolvimento são um só, ou seja, a máquina do (a) desenvolvedor (a). É nesse ambiente que o produto é desenvolvido e, muitas vezes, implementado local para testes iniciais.
- Staging: também é chamado de ambiente de teste ou homologação, é onde é feito o deploy da aplicação para que seja testada pela equipe desenvolvedora, ou, ainda, para acesso e acompanhamento dos resultados pelos demais interessados. Aqui, busca-se identificar inseguranças, falhas de desempenho, quais melhorias poderiam ser feitas, se a expectativa de entrega está de acordo com o definido no planejamento e etc.
- Produção: Esse ambiente requer extremo cuidado pois é aquele que os usuários terão acesso à aplicação. Ainda veremos melhor adiante, porém, quando falamos em “modelo em produção”, estamos falando exatamente desse ambiente, em que alguma coisa (uma web page, um bot, um programa, etc) permitirá que o usuário final possa, por exemplo, inserir os dados e receber o retorno da predição.
Nem sempre esse processo ocorre linearmente como apresentado acima, ou seja, pode-se ir e voltar, ou, até mesmo, após uma rápida prototipação, já disponibilizar um ambiente para o usuário testar enquanto o produto amadurece e os incrementos vão ocorrendo.
3) O deploy e o ciclo de vida da Engenharia de Machine Learning
Já bem se sabe que um projeto de Ciência dos Dados não termina com a métrica do modelo. Além do fato de que essa métrica precisa ser traduzida para uma linguagem de negocio de forma que se possa avaliar os resultados, levando em consideração os custos, projeções de faturamento e etc, o modelo desenvolvido precisa ser disponibilizado para aqueles que vão utilizá-los, seja um cliente da empresa, seja algum outro time interno. Ou seja, é aquele famoso momento de colocar o modelo em produção.
De forma semelhante ao processo de software que conversamos, o ciclo de vida do processo dessa implementação do modelo ocorre também em algumas etapas. Wilson (2020), em seu glorioso Machine Learning Engineering, nos apresenta o seguinte roteiro desse processo, embora não se limite exclusivamente a ele:
- Planejamento: definir o que e quando se deseja produzir (adiciono aqui a definição de métricas de avaliação, pois, no final de tudo, precisamos mensurar de alguma maneira o sucesso do processo). Devemos lembrar que muitos projetos de soluções de Machine Learning falham principalmente por falta de planejamento ou por buscar desenvolver uma solução que não seria adequada. Logo, é uma das etapas mais importante ( e isso em qualquer tipo de projeto).
- Definição do escopo: definir o que de fato será produzido e testado. Isso é importante também por interesses do time de negócios, pois precisam saber se e como o que estamos fazendo irá realmente resolver um determinado problema, quanto tempo isso vai levar e se gerará valor.
- Experimentação: a implementação funcionará? podemos compará-la com outras abordagens? Em muitas situações, o tempo levado nessa etapa precisa ser adequado, para que não se despenda tempo de mais e nem de menos.
- Desenvolvimento: desenvolvimento em si da aplicação.
- Implementação: Integração da nossa solução em um ambiente de produção existente de forma a disponibilizar aos usuários e monitorar a performance.
- Avaliação e Melhorias: avaliar, com base nas métricas pré-definidas, os resultados e realizar os ajustes e mudanças adequadas. Ou seja, a solução de ML que desenvolvemos está funcionando como deveria?
Temos que estar cientes, assim como vimos antes, que esse processo aqui pode não ocorrer de forma linear, sendo iterativo e também cíclico entre etapas. Isso ocorre porque cada empresa tem sua própria metodologia e processos, além disso, nenhum projeto é igual e cada um tem sua própria demanda. Mas vamos colocar esses “dependes” de lado e vamos pensar num exemplo que se aproxime da realidade.
Suponhamos que nosso time de cientistas dos dados esteja desenvolvendo uma solução de diagnóstico de doença cardiovascular (esse contexto será melhor apresentado na seção a seguir) para uma empresa terceira e estamos na etapa de experimentação inicial de alguns algoritmos. Suponhamos também que empresa terceira precisa iniciar alguns testes para que o time de especialistas dela esteja acostumado com a aplicação o quanto antes para que se tenha uma melhor eficiência no momento de utilizá-la (ou seja, não irão ainda tirar conclusões sobre diagnóstico retornado pelo modelo). Note que o objetivo aqui não é necessariamente ter o produto final (o modelo completamente ajustado e retornando a predição com eficiência), mas apenas ter um modelo parcial que os permita fazer testes, alinhar a utilização e, a depender, validar algumas hipóteses.
Esse momento, embora o projeto esteja ainda longe de ser finalizado, se encaixa como um momento em que precisamos colocar o modelo (mesmo que incompleto) em produção.
No processo de predição de uma nova observação, o que acontece: recebemos um conjunto de dados (nesse caso, de um paciente novo) e realizamos a predição. Como fazer com que seja possível que o médico especialista envie esses dados do paciente? São várias as possibilidades. Mas vamos pensar em uma bem simples? Poderíamos desenvolver a API que recebe as requisições com os dados, deixar disponível em um ambiente na nuvem (ou em um servidor próprio), criar um formulário web local e permitir com que o profissional preencha com os dados e receba o resultado (o que mais poderíamos fazer aqui? adoraria que deixassem nos comentários).
Ou seja, teríamos colocado um modelo em produção ainda “no meio” do projeto.
Outra situação é o caso da empresa cliente querer apresentar a solução para seus diretores e reforçar o argumento do benefício dela, ou buscar um budget maior.
No fim das contas a mensagem que quero passar até aqui é: a dinâmica de implementação da solução dependerá das demandas de negócios e nós, enquanto cientistas de dados, precisamos estar cientes disso pois pautará nossas ações, como também saber que as reviravoltas acontecem nos projetos e precisamos estar preparados (se pudermos).
4) O contexto de negócio que usaremos nas postagens seguintes dessa série
Para nos servir de contexto, usaremos esta sugestão de projeto. Contudo, aqui, como já dito, não nos ateremos às demais etapas em um projeto de DS. A ideia de ter um contexto é apenas para nos aproximar um pouco mais da realidade, visto que ele, embora ofereça limitações, também serve de guia. Contudo, vamos adicionar mais um objetivo ao conjuntos daqueles no referido link, sendo o seguinte: precisamos entregar uma aplicação em que o cliente possa fazer requisições, enviando os dados, e, ai, retornamos o resultado do diagnóstico.
No link também possui a fonte dos dados, contudo, aqui utilizaremos uma amostragem daquele dataset para fins de simplificação. Logo, não nos ateremos à performance do modelo, partindo da suposição de que está adequada.
5) Resumindo a solução que iremos desenvolver
Nas postagens 1 e 2 nós desenvolveremos nossa API em Python com Flask. O resultado final será o seguinte: a API receberá o dado que será usado para a predição, carregará e aplicará os scalers e o modelo salvo e, por fim, retornará a predição. Na segunda postagem nós iremos containerizar essa API.
Por fim, na terceira postagem, iremos trabalhar um pouco mais nossa API e a construção da imagem docker (veremos o que é isso) a fim de aprofundar mais nos conceitos. Adicionalmente, construiremos um formulário web para que o cliente possa preencher e enviar os dados.
6) Conclusão
Vimos aqui que deploy na verdade é basicamente disponibilizar a solução que estamos desenvolvendo de forma que os usuários possam utilizar. Para isso, partimos lá dos processos de desenvolvimento de software e chegamos no roadmap da Engenharia de Machine Learning.
Algo importante que salientamos é que o contexto de negócio define e guia nossas ações e entregas do projeto e nós, enquanto profissionais de dados, precisamos nos atentar a ele.
Resumimos aqui nossa proposta de solução que desenvolveremos: uma REST API com Flask para um modelo simples de diagnóstico de doenças cardiovasculares. Posteriormente colocaremos nossa API em um container Docker e, por fim, construiremos um formulário para enviar requisições e faremos o deploy do container no Heroku!
Bom, se você chegou até aqui, agradeço pelo seu tempo de leitura e peço que compartilhe suas impressões e críticas, se assim o quiser 😃. Se notou que me equivoquei em alguma parte, adoraria que pudesse me apontar.
Ficarei feliz e honrado se “nos vermos” novamente na próxima postagem dessa série 😍.
Que o conhecimento seja compartilhado; o aprendizado, contínuo!
7) Referências
SOMMERVILLE, Ian. Engenharia de software. 10ª. Edição. São Paulo: Addison Wesley, 2018.
WILSON, ben T. Machine Learning Engineering. v. 2, Manning, 2020.