BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Artigos Aprendizado de máquinas em Java com o Deep Java Library da Amazon

Aprendizado de máquinas em Java com o Deep Java Library da Amazon

Favoritos

Pontos Principais

  • Falta padronização no desenvolvimento aplicações com aprendizado de máquinas em Java;

  • A JSR 381 foi desenvolvida para preencher essa lacuna;

  • O Deep Java Library (DLJ) da Amazon é uma das diversas implementações desta nova padronização;

  • Uma parte da JSR 381 é o reconhecimento visual (VisRec) de imagens;

  • O DLJ inclui um conjunto de modelos pré-treinados.

https://www.deepnetts.com/blog/deep-netts-community-edition

O interesse no aprendizado de máquinas tem crescido constantemente nos últimos anos. Especificamente, entre as empresas que usam o aprendizado de máquinas para reconhecimento de imagem em diversos casos de uso. Existem aplicações na indústria automotiva, saúde, segurança, varejo, rastreamento automatizado de produtos em centros de distribuição, fazenda e agricultura, reconhecimento de alimentos e até tradução em tempo real, apontando a câmera do seu telefone. Graças ao aprendizado de máquinas e o reconhecimento visual, as máquinas podem detectar câncer e COVID-19 nas ressonâncias magnéticas e tomografias computadorizadas.

Hoje, muitas soluções são desenvolvidas principalmente em Python usando ferramentas de código aberto ou proprietárias, cada uma com suas próprias APIs. Apesar da popularidade do Java pelas companhias, não existe padronização para desenvolver aplicativos de aprendizado de máquinas em Java. A JSR-381 foi desenvolvida para preencher essa lacuna, oferecendo aos desenvolvedores Java um conjunto padronizado, flexíveis e compatíveis com as APIs Java para desenvolver aplicações de reconhecimento visual (VisRec), como classificação de imagens e detecção de objetos. A JSR-381 possui várias implementações que utilizam plataformas de aprendizado de máquina, como: TensorFlow, MXNet e DeepNetts. Uma dessas implementações é a Deep Java Library (DJL), uma biblioteca de código aberto desenvolvida pela Amazon para aprendizado de máquinas em Java. A DJL oferece chamadas para os frameworks populares de aprendizado de máquina, como: TensorFlow, MXNet e PyTorch, agrupando as chamadas nas funções de processamento de imagem, tornando-a uma opção flexível e simples para usuários da JSR-381.

Neste artigo, demonstramos como os desenvolvedores Java podem usar a API JSR-381 VisRec, implementando um classificador de imagens ou detector de objetos, utilizando modelos pré-treinados da DJL e com menos de 10 linhas de código.

Reconhecendo dígitos escritos à mão usando um modelo pré-treinado

Um aplicativo útil e exemplo no estilo "olá mundo" de reconhecimento visual é reconhecer dígitos manuscritos. Reconhecer dígitos manuscritos é aparentemente fácil para um ser humano. Graças à capacidade de processamento e à cooperação dos subsistemas de correspondência visual e de padrões em nossos cérebros, geralmente podemos discernir corretamente o dígito correto a partir de um documento mal escrito. No entanto, essa tarefa aparentemente simples é incrivelmente complexa para uma máquina devido as muitas variações possíveis. Este é um bom caso de uso para o aprendizado de máquinas, especialmente para reconhecimento visual. O repositório da JSR 381 tem um ótimo exemplo que usa a API JSR-381 VisRec para reconhecer corretamente dígitos manuscritos. Este exemplo compara dígitos manuscritos com o conjunto de dados de dígitos manuscritos MNIST, um banco de dados disponível publicamente com mais de 60 mil imagens. Prever o que uma imagem representa é chamado de classificação de imagem. Esse exemplo analisa uma nova imagem e tenta determinar as probabilidades de qual dígito é representado.

Para esta tarefa, a API VisRec fornece uma interface ImageClassifier que pode ser especializada para classes Java específicas para entrada de imagens usando parâmetros genéricos. Ela também fornece o método classify() que executa a classificação de imagens e retorna um Map de probabilidades de classe para todas as classes (classificações) de imagens possíveis. Por convenção na API VisRec, cada modelo fornece um método estático builder() que retorna um construtor correspondente e permite que o desenvolvedor defina todas as configurações relevantes, por exemplo: imageHeight e imageWidth.

Para definir um classificador de imagem para dígitos manuscrito, configure como será tratado a entrada usando o inputClass (BufferedImage.class). Isso serve para especificar a classe que será usada para representar a imagem. Defina o imageHeight(28) e imageWidth(28) para redimensionar a imagem de entrada para o tamanho 28x28, pois esse foi o tamanho original usado no treinamento do modelo. Depois de criar o objeto classifier, envie a imagem de entrada ao classificador para reconhecer essa imagem.

File input = new File("../jsr381/src/test/resources/0.png");

// Usa o modelo pré-treinado da pasta mlp
Path modelPath = Paths.get("../jsr381/src/test/resources/mlp");

ImageClassifier<BufferedImage> classifier =
       NeuralNetImageClassifier.builder()
           // A entrada é uma imagem e deve ser tratada como um BufferedImage
           .inputClass(BufferedImage.class)
           // redimenciona a imagem para o tamanho 28 x 28
           .imageHeight(28)
           .imageWidth(28)
           .importModel(modelPath)
           .build();

// Executa a classificação e pega seu resultado
Map<String, Float> result = classifier.classify(input);

// Imprime o resultado
for (Map.Entry<String, Float> entry : result.entrySet()) {
   System.out.println(entry.getKey() + ": " + entry.getValue());
}

A execução desse código produz a seguinte saída:

0: 0.9997633
2: 6.915607E-5
5: 2.7744078E-5
6: 6.1097984E-5
9: 3.8322916E-5

O modelo identificou cinco opções possíveis para o dígito da imagem com as probabilidades associadas a cada opção. O classificador prevê corretamente que o dígito subjacente é 0 (zero) com uma probabilidade esmagadora de 99,98%.

Uma generalização desse caso é a questão do que fazer quando precisar detectar objetos diferentes na mesma imagem?

Reconhecendo objetos usando um modelo pré-treinado do Single Shot Detector

O Single Shot Detector (SSD) é um mecanismo que detecta objetos em imagens usando uma única rede neural profunda. Neste exemplo, vamos reconhecer objetos em uma imagem usando um modelo SSD pré-treinado. A detecção de objetos é uma das mais desafiadoras tarefa de reconhecimento visual. Além de classificar os objetos da imagens, a detecção de objetos identifica a localização dos objetos na imagem. Também pode desenhar uma caixa delimitadora em torno de cada objeto detectado, juntamente com um rótulo da classe (classificação).

O SSD é um mecanismo criado recentemente para o aprendizado de máquina que detecta objetos rapidamente, além de manter a precisão em comparação com modelos que utilizam computação mais intensiva. Para conhecer mais sobre o modelo SSD veja o post Understanding SSD MultiBox - Real-Time Object Detection In Deep Learning e este exercício do livro Dive into Deep Learning.

Com a implementação DJL do JSR-381, os usuários podem acessar uma implementação pré-treinada do modelo SSD. A DJL usa o ModelZoo para simplificar o deploy dos modelos. No código a seguir, carregamos um modelo pré-treinado com o ModelZoo.loadModel(), instanciamos uma classe de detector de objetos e aplicamos esse modelo em uma imagem de amostra.

// Define um critério para pesquisar um modelo que combina com as necessidades do usuário
Criteria<BufferedImage, DetectedObjects> criteria =
        Criteria.builder()
                .setTypes(BufferedImage.class, DetectedObjects.class)
                // Procura um modelo para detectar objetos
                .optApplication(Application.CV.OBJECT_DETECTION)
                .build();

// Carrega o modelo e cria um SimpleObjectDectector
try (ZooModel<BufferedImage, DetectedObjects> model = ModelZoo.loadModel(criteria)) {
   // SimpleObjectDetector is a high level JSR-381 API in charge of detect object
   SimpleObjectDetector objectDetector = new SimpleObjectDetector(model);

   // Load image
   BufferedImage input =
       BufferedImageUtils.fromUrl(
           "https://djl-ai.s3.amazonaws.com/resources/images/dog_bike_car.jpg");
   // detect objects
   Map<String, List<BoundingBox>> result = objectDetector.detectObject(input);

   for (List<BoundingBox> boundingBoxes : result.values()) {
       for (BoundingBox boundingBox : boundingBoxes) {
           System.out.println(boundingBox.toString());
       }
   }
}

Vamos detectar os objetos da imagem a seguir:

Executando o código com essa imagem, temos o seguinte resultado:

BoundingBox{id=0, x=124.0, y=119.0, width=456.45093, height=338.8393, label=bicycle, score=0.9538524}
BoundingBox{id=0, x=469.0, y=78.0, width=225.19464, height=92.147675, label=car, score=0.99991035}
BoundingBox{id=0, x=128.0, y=201.0, width=210.51933, height=341.7647, label=dog, score=0.9375212}

Se quiser adicionar as caixas delimitadoras em torno de cada objeto detectado, podemos fazê-lo com apenas algumas linhas de código adicionais. Para obter mais informações, consulte o exemplo completo no GitHub. O modelo classifica os três objetos de interesse (bicicleta, carro e cachorro), desenha uma caixa delimitadora em torno de cada um e fornece um nível de confiança refletido pelas probabilidades.

Vale ressaltar que a precisão da detecção em modelos pré-treinados depende das imagens usadas para treinar o modelo. A precisão do modelo pode ser aprimorada, treinando novamente ou desenvolvendo um modelo personalizado com um conjunto de imagens mais representativas do aplicativo final. Essa abordagem, no entanto, consome tempo e requer acesso a uma grande quantidade de dados de treinamento. Em muitas aplicações de ML, vale a pena estabelecer uma linha de base com um modelo pré-treinado. Isso pode economizar uma quantidade significativa de tempo associado à coleta, preparação de dados e treinamento do modelo a partir do zero.

Próximos passos?

Neste post, apenas mostramos o que podemos fazer com a implementação DJL da API JSR-381. Podemos explorar e implementar muitos mais modelos com o repositório de modelos pré-treinados no ModelZoo ou adicionar o seu próprio modelo.

Te convidamos a conferir o DJL, uma biblioteca de código aberto criada por desenvolvedores Java da Amazon para a comunidade Java. Tentamos simplificar o desenvolvimento e a implantação do aprendizado de máquina em Java. Por favor, junte-se a nós em nossa missão.

Existem muitos casos de uso para DJL, podemos desenvolver um aplicativo de perguntas e resposta para atendimento ao cliente, implementar estimativa de pose em suas poses de ioga ou treinar seu próprio modelo para detectar invasores em seu quintal. Nosso kit inicial com Spring Boot também facilita a integração do ML com suas aplicações que usam via Spring Boot. Você pode aprender mais sobre a DJL através do nosso blog introdutório, site e repositório de exemplos. Acesse o repositório do Github e colabore conosco no canal do Slack.


Referências


Sobre os autores

Frank Liu é engenheiro de software na AWS AI. Ele se concentra na criação de ferramentas inovadoras de deep learning para engenheiros de software e cientistas. Nas horas vagas, gosta de fazer caminhadas com amigos e familiares.

Xinyu Liu é gerente de desenvolvimento de software na AWS AI. Ele é apaixonado por Machine Learning e sistemas distribuídos em larga escala.

Frank Greco é o fundador e CEO da Crossroads Technologies. Ele é consultor sênior de tecnologia e arquiteto corporativo, trabalhando com cloud e ferramentas de IA / ML para desenvolvedores. Ele é Java Champion, presidente da NYJavaSIG e dirige a conferência International Machine Learning for the Enterprise na Europa. Dedica seu tempo livre a tocar violão.

Zoran Sevarac é CEO da Deep Netts. Trabalha na construção de ferramentas de Deep Learning para desenvolvedores Java e na criação de padronizações Java para IA. Ele é professor da Universidade de Belgrado e Java Champion. Nas horas vagas, ele toca violão.

Balaji Kamakoti é gerente sênior de produtos na AWS AI. Ele trabalha com produtos que tornam o Deep Learning mais acessível aos desenvolvedores. Em seu tempo livre, gosta de jogar tênis e tocar Sarod, um instrumento de cordas sem trastes.

Um agradecimento especial às equipes da JCP e JSR-381 por suas valiosas contribuições:

Kevin Berendsen, Sandhya Kapoor, Werner Keil, Constantin Drabo, Ankara Parida, Melissa Mckay, Buddha Jyoti Prasad, Shreya Gupta, Amit Nagesh, Heather VanCura e Harold Ogle.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT