Como eu transformei a empresa em que trabalho em uma empresa de Deep Learning em menos de 1 ano

Arnaldo Gualberto
Ensina.AI
Published in
8 min readMay 4, 2018

Do clássico ao Machine Learning

Atualmente eu trabalho na Vsoft Tecnologia, uma empresa líder em monitoramento de aulas teóricas e práticas em auto-escolas. O setor de pesquisa, ao qual pertenço, é especializado em biometria de face e de impressões digitais, com algoritmos entre os melhores do Brasil e do mundo de acordo com o FVC-onGoing. Porém, até meados de 2016, a maior parte dos produtos ainda eram baseados em processamento digital de imagens e abordagens clássicas.

No final de 2016, fui contratado pela Vsoft para fazer um projeto de detecção e reconhecimento de semáforos como freelancer. Depois de 3 meses gravando vídeos, gabaritando semáforos, treinando modelos e embarcando a solução em um Raspberry Pi, o trabalho estava pronto. Esse projeto, além de ter sido meu primeiro problema real de Machine Learning, também marcou o início do aprendizado de máquina nos projetos da empresa. Começava ali um novo jeito de fazer pesquisa…

Após esse projeto, meu contrato como freelancer foi estendido para mais alguns projetos. Entre tantos outros, desenvolvi um detector de faces/cabeças para contar pessoas em salas de aula (nós vamos voltar a ele mais tarde). Novamente, através do Machine Learning, conseguimos resultados bem superiores a detectores padrões de face como os das bibliotecas OpenCV e Dlib. Abaixo, segue uma demonstração do resultado:

Em abril de 2017, fui então contratado como pesquisador. Minha missão agora era tanto melhorar os produtos que já tínhamos quanto permitir a criação de novos produtos usando Machine Learning. Em poucos meses, mais de 10 projetos foram concluídos, o ML já estava em praticamente todos os produtos, e o treinamento/implementação de modelos já fazia parte do dia-a-dia da empresa.

ML para cá, ML para lá, mas até agora nada de Deep Learning. Se você chegou até aqui, já deve estar pensando:

Afinal, cadê o Deep Learning nessa história?

O início do Deep Learning

Nos meses seguintes, começamos a sondar onde poderíamos aplicar Deep Learning na empresa. Como alguns dos produtos da Vsoft rodam diretamente no cliente, precisávamos escolher um problema que pudesse ser resolvido por uma rede capaz de rodar em um computador sem GPU ou até mesmo ser embarcada em um celular. Além disso, também tínhamos que escolher um problema que tivesse uma quantidade razoável de dados, já que, como todo mundo sabe, isso é praticamente um requisito para um projeto de Deep Learning. Logo, com praticamente 40.000 faces e 90.000 exemplos negativos (não-face) gabaritados em quase 9.000 imagens de sala de aula, decidimos retomar o projeto de detecção de pessoas em sala de aula.

Vale salientar que o nosso banco de sala de aula é um banco extremamente difícil. As fotos foram tiradas em diversas salas de aula sem nenhuma restrição de câmera, posição ou tipo de imagem. Além disso, há faces sob diversas condições de iluminação, pose, qualidade, tamanho e oclusão.

O treinamento da rede

No começo de Agosto de 2017, dei início ao treinamento do meu primeiro problema real (e também o primeiro da empresa) em Deep Learning. Como sempre gosto de fazer ao iniciar um projeto novo, passei uma semana lendo trabalhos na literatura e tutoriais na internet sobre detecção de objetos com Deep Learning. Lembro que li sobre a R-CNN, Fast(er) R-CNN, Single-Shot Detectors (SSD), YOLO (v1 e v2), SqueezeDet, entre outros.

Os 4 meses seguintes foram reservados para o ajuste de hiperparâmetros. Como esse era meu primeiro projeto, aproveitei para testar na prática todas as recomendações que eu já havia lido sobre o treinamento de redes neurais: as melhores funções de ativação, os melhores otimizadores, a quantidade de filtros/camadas, etc… Ao todo, treinei mais de 450 redes diferentes. Para piorar, na época nós ainda não tínhamos um computador com GPU. Cada treinamento da rede, então, demorava em média 20–30 minutos (algumas redes duravam mais de uma hora!). Apesar disso, treinar todas essas redes meu deu um insight muito bom sobre o treinamento. Hoje, todo esse expertise me ajuda bastante nos meus novos treinamentos de rede.

Outro problema que tive de enfrentar foi relacionado aos dados. Após os 2 primeiros meses de treinamento, percebemos que os nossos dados apresentavam problemas de gabarito. Com ajuda de um estagiário, nós resolvemos praticamente todos esses erros e ainda aumentamos o conjunto de treinamento para quase 300.000 imagens (agora, aproximadamente 120.000 exemplos positivos e 180.000 negativos). Passamos praticamente 1 mês nesse processo.

O mês de dezembro foi reservado para o ajuste fino da rede. Mexemos cuidadosamente em alguns hiperparâmetros visando melhorar a nossa taxa no banco de teste. Quando finalmente terminamos esse ajuste, tínhamos aumentando a F-measure do nosso antigo detector de 85,65% para 89,55%. A fins de comparação, os detectores de face da OpenCV e Dlib apresentam a F-measure de 61,14% e 62,09%, respectivamente.

Os desafios para colocar em produção

Com o novo detector baseado em Deep Learning pronto, restava agora colocá-lo em produção. Apesar do treinamento ter sido em Python, eu escolhi o Tensorflow como framework justamente por ele ser originalmente escrito e ter uma api em C++. Além disso, como o treinamento foi todo feito em Python, eu só iria ter que carregar o modelo em C++ e fazer predição. “Não deve ser tão difícil assim!”, eu pensei. Doce ilusão…

O primeiro passo para integrar o Tensorflow em um programa C++ do Visual Studio seria buildá-lo a partir do código fonte. No próprio repositório do Tensorflow você encontra instruções bem detalhadas para isso. Segui as instruções corretamente e o build funcionou num projeto de exemplo, mas quando tive que colocá-lo no projeto do Visual Studio, onde ele supostamente deveria funcionar, eu obtive o seguinte erro:

error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in file.obj

Lembro que passei o restante do mês de dezembro e uma parte do mês de janeiro tentando resolver esse erro. Não consegui. Nesse meio tempo, também começaram a aparecer outras demandas para eu resolver e meio que fui deixando isso de lado. Apenas em abril, tive a oportunidade de retornar a esse erro. Acho que esse 2 a 3 meses foram muito bons para esfriar a cabeça e ter ideias novas.

Finalmente, no começo de abril consegui resolver o problema de build (confira meu post no Medium ensinando como resolvê-lo ). Logo, o restante do mês foi reservado para incorporar o modelo, escrever documentação, teste unitário, release notes, e gerar as libs/dlls necessárias para o pessoal do desenvolvimento colocar em produção. Nos próximos dias, o sistema já deve estar em produção contando pessoas pelas salas de aula do Norte/Nordeste.

Resultados

Para fins de comparação, segue uma tabela comparando os detectores da OpenCV, Dlib com o antigo modelo com Machine Learning e o atual com Deep Learning, avaliados no nosso banco de teste (8165 detecções em 485 imagens):

Além disso, o tempo médio de detecção para uma imagem de 1280x720 subiu apenas de 0,47s (com o modelo baseado em Machine Learning) para 0,49s — considerando um computador sem GPU. Ou seja, conseguimos aumentar nossas taxas sem praticamente alterar o nosso tempo de detecção!

E quanto às detecções? Para finalizar os resultados, vamos observar algumas das imagens e as detecções pelo modelo baseado em Deep Learning. Primeiro, vamos aos resultados nas imagens de sala de aula:

O banco que utilizamos não é público, logo a identidade das pessoas detectadas foram preservadas pós-detecção.

Resultado da detecção para algumas imagens do banco de teste, isto é, imagens nunca vistas pela rede durante o treinamento. Os rostos das pessoas foram embaçados pós-detecção para preservação de identidade.

Na figura abaixo, por sua vez, podemos ver alguns exemplos de pessoas detectadas pelo modelo. Repare que a rede foi capaz de detectar cabeças em todas as diferentes condições citadas anteriormente: iluminação, qualidade, pose e oclusão.

Exemplos de verdadeiros positivos (TP) detectados pela rede. Algumas imagens foram adicionadas tarjas-pretas para preservação de identidade.

Dicas para quem quer fazer o mesmo

A minha primeira experiência em um problema real de Deep Learning serviu para me apontar alguns erros que não pretendo cometer novamente e ver que algumas coisas que fiz foram importantes para o sucesso do projeto. Logo, se eu tivesse que destacar os pontos mais importantes para quem quer tentar trilhar o mesmo caminho, eu diria que seriam esses:

  • Procure por quem fez algo parecido com o que você quer fazer. Leia artigos científicos parecidos com seu tema e busque por pessoas que já fizeram. Tanto o GitHub quando o próprio Medium também são boas fontes de pesquisa nessa etapa, tanto para código quanto para relatos de experiência — desde arquiteturas e hiperparâmetros até ideias e soluções de problemas.
  • Examine profundamente seus dados. Pense se eles são suficientes, procure por erros, visualize e analise. Todo segundo gasto aqui eu considero um investimento e essa etapa é com certeza a mais importante. Lembre-se da célebre frase de Abraham Lincoln:

“Se eu tivesse 6 horas para cortar uma árvore, eu passaria 4 afiando o machado.”

  • Use o framework Keras para treinamento do seu modelo. Mesmo que o seu produto final não seja em Python, o Keras permite que você faça o teste de diversos modelos e hiperparâmetros de forma fácil e rápida. Eu escolhi o Tensorflow para esse primeiro projeto pois pensava que, além de ser mais fácil integrar com o C++, eu iria precisar da flexibilidade que a implementação de mais baixo nível do Tensorflow proporcionava. A verdade é que pouquíssimas coisas que eu implementei já não estavam disponíveis no Keras. E, no fim das contas, ela nem permaneceram no meu modelo final. Uma boa estratégia é: prototipe em Keras e depois porte o modelo final para o melhor framework de acordo com a sua necessidade.

Considerações Finais

Meu primeiro problema real com Deep Learning foi muito bom para me mostrar na prática como as coisas funcionam. Ganhei experiência com ajuste de hiperparâmetros, enfrentei problema com os dados e vi que colocar um modelo em produção é bem mais difícil do que parece. Verdade seja dita, todo esse processo foi bem desgastante, mas a recompensa valeu a pena. Escolher parâmetros em problemas reais é bem diferente de seguir tutoriais na internet e dados reais são bem mais difíceis que bancos de competições por aí. Além disso, converter um código em Python para um projeto C++ é bem desafiador, ainda mais quando a documentação da biblioteca escolhida é bem defasada como a do Tensorflow.

No fim das contas, o tempo bruto do projeto foram 8 meses (agosto/2017 — abril/2018). No entanto, o tempo líquido foi bem menor: 4 meses, sendo 3 meses treinando a rede + 1 mês para colocar em produção. Só relembrando, dos demais 4 meses, 3 foram gastos em outras demandas e 1 mês foi gasto para corrigir/aumentar o gabarito. Vale salientar que o tempo de treinamento da rede poderia ser ainda menor se, na época, eu tivesse acesso a computador com GPU. Hoje, isso já não é mais um empecilho.

Por fim, é importante lembrar de toda a ajuda que tive durante a execução desse projeto. Todo o pessoal da pesquisa — em especial o João Roberto (ex-estagiário) e o Arthur Araújo— , além da infra-estrutura fornecida pela Vsoft, foram essenciais para o sucesso do projeto.

--

--