Aprendizado de máquina industrial: 10 princípios de design

Aprendizado de máquina industrial: 10 princípios de design

Hoje em dia, todos os dias são criados novos serviços, aplicativos e outros programas importantes que permitem criar coisas incríveis: desde software para controlar um foguete SpaceX até interagir com uma chaleira na sala ao lado através de um smartphone.

E, às vezes, todo programador novato, seja ele um startup apaixonado ou um Full Stack ou Cientista de Dados comum, mais cedo ou mais tarde chega à conclusão de que existem certas regras para programar e criar software que simplificam muito a vida.

Neste artigo, descreverei brevemente 10 princípios de como programar o aprendizado de máquina industrial para que possa ser facilmente integrado a uma aplicação/serviço, com base na metodologia App de 12 fatores. sugerido pela equipe Heroku. Minha iniciativa é aumentar o conhecimento dessa técnica, que pode ajudar muitos desenvolvedores e pessoas de ciência de dados.

Este artigo é o prólogo de uma série de artigos sobre aprendizado de máquina industrial. Neles falarei ainda sobre como realmente fazer um modelo e lançá-lo em produção, criar uma API para ele, além de exemplos de diversas áreas e empresas que possuem ML integrado em seus sistemas.

Princípio 1: Uma base de código

Alguns programadores nos primeiros estágios, por preguiça de descobrir (ou por algum motivo próprio), esquecem o Git. Ou eles esquecem completamente a palavra, ou seja, jogam arquivos uns para os outros na unidade/apenas jogam texto/enviam por pombos, ou não pensam em seu fluxo de trabalho e enviam cada um para seu próprio branch e depois para o mestre.

Este princípio afirma: tem uma base de código e muitas implantações.

O Git pode ser usado tanto em produção quanto em pesquisa e desenvolvimento (P&D), onde não é usado com tanta frequência.

Por exemplo, na fase de P&D você pode deixar commits com diferentes métodos e modelos de processamento de dados, para então selecionar o melhor e continuar facilmente trabalhando com ele.

Em segundo lugar, na produção isso é algo insubstituível - você precisará observar constantemente como seu código muda e saber qual modelo produziu os melhores resultados, qual código funcionou no final e o que aconteceu que fez com que ele parasse de funcionar ou começasse a produzir resultados incorretos. . É para isso que servem os commits!

Você também pode criar um pacote do seu projeto, colocando-o, por exemplo, no Gemfury, e depois simplesmente importar funções dele para outros projetos, para não reescrevê-los 1000 vezes, mas falaremos mais sobre isso depois.

Princípio 2: Declarar e isolar claramente as dependências

Cada projeto possui bibliotecas diferentes que você importa de fora para aplicá-las em algum lugar. Quer se trate de bibliotecas Python, ou bibliotecas de outras linguagens para diversos fins, ou ferramentas de sistema - sua tarefa é:

  • Declare claramente as dependências, ou seja, um arquivo que conterá todas as bibliotecas, ferramentas e suas versões que são utilizadas em seu projeto e que devem ser instaladas (por exemplo, em Python isso pode ser feito usando Pipfile ou requisitos.txt. A link que permite uma boa compreensão: realpython.com/pipenv-guide)
  • Isole dependências especificamente para o seu programa durante o desenvolvimento. Você não quer mudar constantemente de versão e reinstalar, por exemplo, o Tensorflow?

Desta forma, os desenvolvedores que futuramente se juntarem à sua equipe poderão se familiarizar rapidamente com as bibliotecas e suas versões que são utilizadas em seu projeto, e você também terá a oportunidade de gerenciar as próprias versões e bibliotecas instaladas para um determinado projeto, o que o ajudará a evitar incompatibilidade de bibliotecas ou de suas versões.

Seu aplicativo também não deve depender de ferramentas de sistema que possam estar instaladas em um sistema operacional específico. Essas ferramentas também devem ser declaradas no manifesto de dependências. Isso é necessário para evitar situações em que a versão das ferramentas (bem como sua disponibilidade) não corresponda às ferramentas do sistema de um determinado sistema operacional.

Assim, mesmo que o curl possa ser usado em quase todos os computadores, você ainda deve declará-lo nas dependências, pois ao migrar para outra plataforma ele pode não estar lá ou a versão não será a que você precisava originalmente.

Por exemplo, seu require.txt pode ser assim:

# Model Building Requirements
numpy>=1.18.1,<1.19.0
pandas>=0.25.3,<0.26.0
scikit-learn>=0.22.1,<0.23.0
joblib>=0.14.1,<0.15.0

# testing requirements
pytest>=5.3.2,<6.0.0

# packaging
setuptools>=41.4.0,<42.0.0
wheel>=0.33.6,<0.34.0

# fetching datasets
kaggle>=1.5.6,<1.6.0

Princípio 3: Configurações

Muitos ouviram histórias de vários desenvolvedores que acidentalmente enviaram código para o GitHub em repositórios públicos com senhas e outras chaves da AWS, acordando no dia seguinte com uma dívida de US$ 6000, ou até US$ 50000.

Aprendizado de máquina industrial: 10 princípios de design

Claro, estes casos são extremos, mas muito significativos. Se você armazena suas credenciais ou outros dados necessários para configuração dentro do código, você está cometendo um erro e acho que não há necessidade de explicar o porquê.

Uma alternativa para isso é armazenar configurações em variáveis ​​de ambiente. Você pode ler mais sobre variáveis ​​de ambiente aqui.

Exemplos de dados que normalmente são armazenados em variáveis ​​de ambiente:

  • Nomes de domínio
  • URLs/URIs de API
  • Chaves públicas e privadas
  • Contatos (e-mail, telefones, etc.)

Dessa forma, você não precisa alterar constantemente o código se suas variáveis ​​de configuração mudarem. Isso ajudará você a economizar tempo, esforço e dinheiro.

Por exemplo, se você usar a API Kaggle para realizar testes (por exemplo, baixar o software e executar o modelo por meio dele para testar se o modelo funciona bem), então as chaves privadas do Kaggle, como KAGGLE_USERNAME e KAGGLE_KEY, devem ser armazenados em variáveis ​​de ambiente.

Princípio 4: Serviços de Terceiros

A ideia aqui é criar o programa de forma que não haja diferença entre recursos locais e de terceiros em termos de código. Por exemplo, você pode conectar MySQL local e de terceiros. O mesmo se aplica a várias APIs, como Google Maps ou Twitter API.

Para desabilitar um serviço de terceiros ou conectar outro, basta alterar as chaves de configuração nas variáveis ​​​​de ambiente, das quais falei no parágrafo acima.

Assim, por exemplo, em vez de especificar sempre o caminho para os arquivos com conjuntos de dados dentro do código, é melhor usar a biblioteca pathlib e declarar o caminho para os conjuntos de dados em config.py, para que não importa qual serviço você usa (para exemplo, CircleCI), o programa conseguiu descobrir o caminho para os conjuntos de dados levando em consideração a estrutura do novo sistema de arquivos no novo serviço.

Princípio 5. Construir, lançar, tempo de execução

Muitas pessoas na ciência de dados consideram útil melhorar suas habilidades de escrita de software. Se quisermos que nosso programa trave o menos possível e funcione sem falhas pelo maior tempo possível, precisamos dividir o processo de lançamento de uma nova versão em 3 etapas:

  1. Etapa montagem. Você transforma seu código simples com recursos individuais em um chamado pacote que contém todo o código e dados necessários. Este pacote é chamado de assembly.
  2. Etapa liberação — aqui conectamos nossa configuração ao assembly, sem o qual não conseguiríamos lançar nosso programa. Agora, esta é uma versão totalmente pronta para lançamento.
  3. Em seguida vem o palco realização. Aqui liberamos o aplicativo executando os processos necessários do nosso lançamento.

Esse sistema de lançamento de novas versões de um modelo ou de todo o pipeline permite separar funções entre administradores e desenvolvedores, permite rastrear versões e evita paradas indesejadas do programa.

Para a tarefa de lançamento, muitos serviços diferentes foram criados nos quais você pode escrever processos para serem executados em um arquivo .yml (por exemplo, no CircleCI é config.yml para suportar o próprio processo). Wheely é ótimo na criação de pacotes para projetos.

Você pode criar pacotes com diferentes versões do seu modelo de aprendizado de máquina e, em seguida, empacotá-los e consultar os pacotes necessários e suas versões para usar as funções que você escreveu a partir daí. Isso irá ajudá-lo a criar uma API para o seu modelo, e seu pacote pode ser hospedado no Gemfury, por exemplo.

Princípio 6. Execute seu modelo como um ou mais processos

Além disso, os processos não deveriam ter dados compartilhados. Ou seja, os processos devem existir separadamente, e todos os tipos de dados devem existir separadamente, por exemplo, em serviços de terceiros como MySQL ou outros, dependendo do que você precisa.

Ou seja, definitivamente não vale a pena armazenar dados dentro do sistema de arquivos do processo, caso contrário, isso pode levar à limpeza desses dados durante a próxima versão/alteração de configurações ou transferência do sistema no qual o programa é executado.

Mas há uma exceção: para projetos de aprendizado de máquina, você pode armazenar um cache de bibliotecas para não reinstalá-las toda vez que lançar uma nova versão, se nenhuma biblioteca adicional ou qualquer alteração tiver sido feita em suas versões. Dessa forma, você reduzirá o tempo de lançamento do seu modelo na indústria.

Para executar o modelo como vários processos, você pode criar um arquivo .yml no qual especifica os processos necessários e sua sequência.

Princípio 7: Reciclabilidade

Os processos executados em seu aplicativo modelo devem ser fáceis de iniciar e parar. Assim, isso permitirá que você implante rapidamente alterações de código, alterações de configuração, dimensione de forma rápida e flexível e evite possíveis falhas na versão de trabalho.

Ou seja, o seu processo com o modelo deve:

  • Minimize o tempo de inicialização. Idealmente, o tempo de inicialização (desde o momento em que o comando de inicialização foi emitido até o momento em que o processo entra em operação) não deve ser superior a alguns segundos. O cache da biblioteca, descrito acima, é uma técnica para reduzir o tempo de inicialização.
  • Termine corretamente. Ou seja, a escuta na porta de serviço é realmente suspensa e novas solicitações enviadas a esta porta não serão processadas. Aqui você precisa estabelecer uma boa comunicação com os engenheiros de DevOps ou entender como funciona (de preferência, é claro, o último, mas a comunicação deve ser sempre mantida, em qualquer projeto!)

Princípio 8: Implantação/Integração Contínua

Muitas empresas utilizam uma separação entre as equipes de desenvolvimento e implantação de aplicativos (disponibilizando o aplicativo para os usuários finais). Isso pode desacelerar bastante o desenvolvimento de software e o progresso em sua melhoria. Também estraga a cultura DevOps, onde o desenvolvimento e a integração são, grosso modo, combinados.

Portanto, este princípio afirma que o seu ambiente de desenvolvimento deve ser o mais próximo possível do seu ambiente de produção.

Isso permitirá:

  1. Reduza o tempo de liberação em dezenas de vezes
  2. Reduza o número de erros devido à incompatibilidade de código.
  3. Isso também reduz a carga de trabalho da equipe, já que os desenvolvedores e as pessoas que implantam o aplicativo agora formam uma equipe.

As ferramentas que permitem trabalhar com isso são CircleCI, Travis CI, GitLab CI e outras.

Você pode fazer acréscimos rapidamente ao modelo, atualizá-lo e iniciá-lo imediatamente, enquanto será fácil, em caso de falhas, retornar muito rapidamente à versão funcional, para que o usuário final nem perceba. Isso pode ser feito de maneira especialmente fácil e rápida se você tiver bons testes.

Minimize as diferenças!!!

Princípio 9. Seus registros

Logs (ou “Logs”) são eventos, geralmente registrados em formato de texto, que ocorrem dentro da aplicação (stream de eventos). Um exemplo simples: "2020-02-02 - nível do sistema - nome do processo." Eles são projetados para que o desenvolvedor possa literalmente ver o que está acontecendo quando o programa está em execução. Ele vê o andamento dos processos e entende se está como o próprio desenvolvedor pretendia.

Este princípio afirma que você não deve armazenar seus logs dentro do seu sistema de arquivos - você deve apenas “enviá-los” para a tela, por exemplo, faça isso na saída padrão do sistema. E desta forma será possível monitorar o fluxo no terminal durante o desenvolvimento.

Isso significa que não há necessidade de salvar logs? Claro que não. Seu aplicativo simplesmente não deveria fazer isso – deixe isso para serviços de terceiros. Seu aplicativo só pode encaminhar logs para um arquivo ou terminal específico para visualização em tempo real ou encaminhá-los para um sistema de armazenamento de dados de uso geral (como o Hadoop). Seu aplicativo em si não deve armazenar nem interagir com logs.

Princípio 10. Teste!

Para o aprendizado de máquina industrial, essa fase é extremamente importante, pois é preciso entender que o modelo funciona corretamente e produz o que você deseja.

Os testes podem ser criados usando pytest e testados usando um pequeno conjunto de dados se você tiver uma tarefa de regressão/classificação.

Não se esqueça de definir a mesma semente para modelos de aprendizagem profunda, para que não produzam resultados diferentes constantemente.

Esta foi uma breve descrição dos 10 princípios e, claro, é difícil usá-los sem tentar e ver como funcionam, então este artigo é apenas um prólogo de uma série de artigos interessantes nos quais irei revelar como criar modelos industriais de aprendizado de máquina, como integrá-los aos sistemas e como esses princípios podem tornar a vida mais fácil para todos nós.

Também tentarei usar princípios legais que qualquer um pode deixar nos comentários se quiser.

Fonte: habr.com

Adicionar um comentário