Machine Learning no iOS com CoreML e React-Native

Se você é como eu e sempre sonhou em desenvolver um aplicativo capaz de diferenciar um cachorro-quente do dachshund do seu vizinho usando seu Iphone, este tutorial é para você. Para fazer isso, usaremos React-Native e aprendizado de máquina. Vamos lá !
As soluções de aprendizado de máquina estão disponíveis há muito tempo na nuvem por meio de APIs, mas exigiam uma conexão com a Internet e podiam ser demoradas e caras para processar.
Com o lançamento do iOS 11, a Apple disponibilizou sua biblioteca de Machine Learning, CoreML, para desenvolvedores. Agora, não é mais necessário ter um servidor poderoso para processar solicitações ou chamar uma API de terceiros. CoreML cuida de tudo com o poder de computação do seu smartphone.
Você está curioso para saber como integrá-lo em seus aplicativos? É mais fácil do que você imagina.
Tomemos como exemplo o famoso aplicativo de paródia Não é cachorro quente, descoberto na série Vale do Silício, que, quando o usuário aponta seu smartphone para um objeto, informa instantaneamente se este está olhando para um cachorro-quente ou não.
Não é cachorro-quente

O que você vai aprender nesta parte

  • Instale seu ambiente
  • Coletar dados
  • Crie seu modelo de classificação de imagens com Turi Create
  • Reconheça um cachorro-quente usando a câmera do seu iPhone

Pré-requisitos

  • Mac OS 10.12+
  • ou Linux (com glibc 2.12+)
  • ou Windows 10 (via WSL)

  • Python 2.7, 3.5 ou 3.6

  • uma arquitetura x86_64

  • Xcode 9

  • iOS 11 +

O que é Turi Create?

É uma ferramenta que "simplifica o desenvolvimento de modelos de machine learning personalizados", que podem ser usados ​​em aplicativos usando a biblioteca CoreML.
Turi Create é baseado no framework Deep Learning MXNet do Apache
Turi Create fornece aos desenvolvedores tecnologia flexível para classificar imagens, detectar objetos, sistemas de recomendação de design, etc.
A ferramenta é extremamente fácil de usar, flexível e rápida.

Sua instalação

Tal como acontece com muitas ferramentas de Machine Learning, python é a linguagem utilizada. Mas não se preocupe, o código é muito simples de entender.
Recomenda-se a utilização de um ambiente virtual, virtualenv, digitando o comando

pip install virtualenv

Se você não tem pip, o gerenciador de pacotes Python, você pode instalá-lo com Homebrew digitando o comando

brew install pip

então,

// Créer un environnement virtuel Python
cd ~
virtualenv venv
// Activer votre environnement virtuel
source ~/venv/bin/activate
// Installer Turi Create
pip install -U turicreate

Coletar dados

Antes de podermos treinar um modelo, precisamos de dados.
Esses dados podem ser encontrados no site IMAGEnet que é um banco de dados de imagens muito grande, com mais de 14 milhões de resultados.
Para nosso projeto, precisamos de duas categorias de imagens: Hotdog e… Not Hotdog.
Segue o link da primeira categoria: http://www.image-net.org/synset?wnid=n07697537.

Você também pode recuperar todos os links usando a API pública, através do botão Baixar na guia Downloads

http://www.image-net.org/api/text/imagenet.synset.geturls?wnid=n07697537

Usando turicreate-easy-scripts

Você pode encontrar no repositório turicreate-easy-scripts um conjunto de scripts que facilitarão sua vida.
Então, depois de clonar os repositórios e instalar as dependências da pasta download-image :

cd download-images
npm install

Você pode executar o comando:

node imagenet-downloader.js http://www.image-net.org/api/text/imagenet.synset.geturls?wnid=n07697537 hotdog

E pegue uma pasta cheia de fotos de cachorros-quentes.
Tudo o que resta é fazer o mesmo para Not Hotdog. Então escolha a(s) categoria(s) que você mais gosta e categorize-as como não-hotdog

node imagenet-downloader.js http://image-net.org/api/text/imagenet.synset.geturls?wnid=n00021939 not-hotdog

Treine o modelo

Uma vez que as imagens foram carregadas e categorizadas, tudo o que resta é treinar o modelo de classificação.
Para fazer isso, você pode usar o script python disponibilizado no repositório baixado anteriormente

cd train-model
python train-model.py


Você obterá após cerca de dez minutos (ou mais, dependendo do número de imagens a serem processadas) um arquivo Classifier.mlmodel que agora podemos usar.
gifml

Criar um projeto React-Native

Primeiro, você precisará criar um novo projeto React-Native.
Abra seu terminal, navegue até a pasta de projetos e digite o seguinte comando:

react-native init notHotDog (ou tout autre nom)

Após alguns minutos, tudo estará instalado e você estará pronto para seguir em frente.

Instale a biblioteca CoreML

Usaremos a biblioteca react-native-core-ml-image

npm install --save react-native-core-ml-image
react-native link

Vá para o seu projeto, depois para a pasta “ios” e clique duas vezes no arquivo notHotDog.xcodeproj para abri-lo no Xcode

Configure o projeto

Por padrão, os projetos React-Native são configurados para usar principalmente o Objective-C. A livraria react-native-core-ml-image sendo escrito em Swift, será necessário alterar alguns parâmetros no projeto
Antes de tudo, teremos que adicionar um arquivo Swift ao projeto


O nome não importa, ele não será usado de qualquer maneira. Aparece então uma mensagem sugerindo que você crie um “Objective-C Bridging Header”: este é o arquivo usado para fazer o link entre o Swift e os arquivos de cabeçalho das Classes Objective-C

Finalmente, a biblioteca sendo escrita em Swift 4.0, você terá que especificar a versão do Swift a ser usada (3.2 sendo a versão padrão).
Clique na raiz do projeto (nãoHotDog), selecione a guia “Build Settings” e, na parte inferior, altere a versão do idioma Swift a ser usado.

Importar o modelo CoreML para o projeto

Antes de passar para a parte de programação, tudo o que resta é importar nosso modelo de classificação de imagens para o projeto notHotDog.
Modelo de arrastar e soltar Classifier.mlmodel e renomeie notHotDog.mlmodelc (não, isso não é um erro de digitação)

CoreML não funciona diretamente com arquivos _.mlmodel, você tem que traduzi-los para _.mlmodelc (c para compilado) primeiro, mas nosso script Python já cuidou disso. (veja a última linha do arquivo train_model.py)

# Export for use in Core ML
model.export_coreml('Classifier.mlmodel')

Permitir acesso à câmera

No arquivo Info.plist, clique no pequeno sinal de mais à direita de cada entrada e adicione “Privacidade – Descrição de uso da câmera” conforme mostrado abaixo

Isso é tudo para a configuração! Resta apenas implementar tudo isso.
código gif

Implemente o código

A primeira coisa a fazer é importar a biblioteca react-native-core-ml-image no projeto. Para este exemplo, todo o código estará no arquivo App.js

import CoreMLImage from 'react-native-core-ml-image'

Em seguida, substitua todo o método render() pelo seguinte:

render() {
    let classification = null;
    if (this.state.bestMatch) {
      if (this.state.bestMatch.identifier && this.state.bestMatch.identifier === "hotdog") {
        classification = "Hotdog";
      } else {
        classification = "Not hotdog";
      }
    }
    return (
      <View style={styles.container}>
          <CoreMLImage modelFile="notHotDog" onClassification={(evt) => this.onClassification(evt)}>
              <View style={styles.container}>
                <Text style={styles.info}>{classification}</Text>
              </View>
          </CoreMLImage>
      </View>
    );
  }

O método na Classificação nos permite receber atualizações quando um novo objeto é classificado. Ele retorna os seguintes dados:

[
{
identifier: "hotdog",
confidence: 0.87
},
{
identifier: "not-hotdog",
confidence: 0.4
}
]

Nós apenas temos que implementar o método na Classificação quem é responsável por encontrar a melhor classificação.

const BEST_MATCH_THRESHOLD = 0.5;
/** */
onClassification(classifications) {
    let bestMatch = null;
    if (classifications && classifications.length) {
      classifications.map(classification => {
        if (!bestMatch || classification.confidence > bestMatch.confidence) {
          bestMatch = classification;
        }
      });
      if (bestMatch.confidence >= BEST_MATCH_THRESHOLD) {
        this.setState({
          bestMatch: bestMatch
        });
      }
      else {
        this.setState({
          bestMatch: null
        });
      }
    }
    else {
      this.setState({
        bestMatch: null
      });
    }
  }

Com base nos dados anteriores, bestMatch será

{
identifier: "hotdog",
confidence: 0.87
}

Aqui está o código completo:

import React, { Component } from "react";
import { Platform, StyleSheet, Text, View } from "react-native";
import idx from "idx";
const BEST_MATCH_THRESHOLD = 0.5;
import CoreMLImage from "react-native-core-ml-image";
export default class App extends Component<{}> {
  constructor() {
    super();
    this.state = {
      bestMatch: null
    };
  }
  onClassification(classifications) {
    let bestMatch = null;
    if (classifications && classifications.length) {
      classifications.map(classification => {
        if (!bestMatch || classification.confidence > bestMatch.confidence) {
          bestMatch = classification;
        }
      });
      if (bestMatch.confidence >= BEST_MATCH_THRESHOLD) {
        this.setState({
          bestMatch: bestMatch
        });
      } else {
        this.setState({
          bestMatch: null
        });
      }
    } else {
      this.setState({
        bestMatch: null
      });
    }
  }
  classify() {
    if (idx(this.state, _ => _.bestMatch.identifier)) {
      if (this.state.bestMatch.identifier === "hotdog") {
        return "Hotdog";
      } else {
        return "Not hotdog";
      }
    }
  }
  render() {
    return (
      <View style={styles.container}>
        <CoreMLImage
          modelFile="notHotDog"
          onClassification={evt => this.onClassification(evt)}
        >
          <View style={styles.container}>
            <Text style={styles.info}>{classify()}</Text>
          </View>
        </CoreMLImage>
      </View>
    );
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "transparent"
  },
  info: {
    fontSize: 20,
    color: "#ffffff",
    textAlign: "center",
    fontWeight: "900",
    margin: 10
  }
});

Tudo o que você precisa fazer é executar o código no seu iPhone (a câmera não funcionará no simulador).
Se você fez tudo certo, o aplicativo pedirá permissão para acessar sua câmera e você poderá distinguir um cachorro-quente do dachshund do seu vizinho.
Obrigado por me ler. Se você gostou do artigo, não hesite em compartilhá-lo nas redes sociais!
Artigo escrito por Jeremias Zarca.