Machine Learning su iOS con CoreML e React-Native

Se sei come me, e hai sempre sognato di sviluppare un'applicazione in grado di differenziare un hotdog dal bassotto del tuo vicino usando il tuo Iphone, questo tutorial fa per te. Per fare ciò, utilizzeremo React-Native e l'apprendimento automatico. Andiamo !
Le soluzioni di Machine Learning sono disponibili da tempo nel cloud tramite API, ma richiedono una connessione Internet e l'elaborazione potrebbe richiedere molto tempo e denaro.
Con il rilascio di iOS 11, Apple ha reso disponibile agli sviluppatori la sua libreria di Machine Learning, CoreML. Ora non è più necessario disporre di un potente server per elaborare le richieste o per chiamare un'API di terze parti. CoreML si occupa di tutto con la potenza di calcolo del tuo smartphone.
Sei curioso di sapere come integrarlo nelle tue applicazioni? È più semplice di quanto potresti pensare.
Prendiamo come esempio la famosa applicazione parodia Non Hotdog, scoperto nella serie Silicon Valley, che, quando l'utente punta il proprio smartphone verso un oggetto, gli dice istantaneamente se quest'ultimo sta guardando un hotdog o meno.
Non hot dog

Cosa imparerai in questa parte

  • Installa il tuo ambiente
  • Raccogliere dati
  • Crea il tuo modello di classificazione delle immagini con Turi Create
  • Riconosci un hotdog usando la fotocamera del tuo iPhone

Prerequisiti

  • Mac OS 10.12+
  • o Linux (con glibc 2.12+)
  • o Windows 10 (tramite WSL)

  • Python 2.7, 3.5 o 3.6

  • un'architettura x86_64

  • Xcode 9

  • iOS 11 +

Cos'è Turi Create?

È uno strumento che "semplifica lo sviluppo di modelli di machine learning personalizzati", che possono quindi essere utilizzati nelle applicazioni che utilizzano la libreria CoreML.
Turi Create si basa sul framework Deep Learning MXNet di Apache
Turi Create fornisce agli sviluppatori una tecnologia flessibile per classificare immagini, rilevare oggetti, sistemi di raccomandazione di progettazione, ecc.
Lo strumento è estremamente facile da usare, flessibile e veloce.

La sua installazione

Come con molti strumenti di Machine Learning, python è la lingua utilizzata. Ma non preoccuparti, il codice è molto semplice da capire.
Si consiglia di utilizzare un ambiente virtuale, virtualenv, immettendo il comando

pip install virtualenv

Se non hai pip, il gestore di pacchetti Python, puoi installarlo con Fatto in casa inserendo il comando

brew install pip

poi,

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

Raccogliere dati

Prima di poter addestrare un modello, abbiamo bisogno di dati.
Questi dati possono essere trovati sul sito web IMAGEnet che è un database di immagini molto grande, con oltre 14 milioni di risultati.
Per il nostro progetto, abbiamo bisogno di due categorie di immagini: Hotdog e... Not Hotdog.
Ecco il link per la prima categoria: http://www.image-net.org/synset?wnid=n07697537.

Puoi anche recuperare tutti i collegamenti utilizzando l'API pubblica, tramite il pulsante Scaricare nella scheda Download

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

Utilizzo di script turicreate-easy

Puoi trovare sul repository turicreate-facili-script una serie di script che ti semplificheranno la vita.
Quindi, dopo aver clonato i repository e installato le dipendenze della cartella download-image :

cd download-images
npm install

Puoi eseguire il comando:

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

E ottieni una cartella piena di immagini di hot dog.
Non resta che fare lo stesso per Not Hotdog. Quindi scegli la categoria o le categorie che ti piacciono di più e classificale come non hotdog

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

Allena il modello

Una volta che le immagini sono state caricate e classificate, non resta che addestrare il modello di classificazione.
Per fare ciò, puoi utilizzare lo script python messo a disposizione nel repository scaricato in precedenza

cd train-model
python train-model.py


Otterrete dopo dieci minuti (o più a seconda del numero di immagini da elaborare) un file Classifier.mlmodel che ora possiamo usare.
gifml

Crea un progetto React-Native

Innanzitutto, dovrai creare un nuovo progetto React-Native.
Apri il tuo terminale, vai alla cartella dei tuoi progetti e inserisci il seguente comando:

react-native init notHotDog (ou tout autre nom)

Dopo pochi minuti, tutto sarà installato e sarai pronto per andare avanti.

Installa la libreria CoreML

Useremo la libreria immagine reattiva-nativa-core-ml

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

Vai al tuo progetto, quindi alla cartella "ios" e fai doppio clic sul file notHotDog.xcodeproj per aprirlo in Xcode

Configura il progetto

Per impostazione predefinita, i progetti React-Native sono configurati per utilizzare principalmente Objective-C. La libreria immagine reattiva-nativa-core-ml essendo scritto in Swift, sarà necessario modificare alcuni parametri nel progetto
Prima di tutto, dovremo aggiungere un file Swift al progetto


Il nome non ha importanza, non verrà comunque utilizzato. Viene quindi visualizzato un messaggio che suggerisce di creare un "Obiettivo-C Bridging Header": questo è il file utilizzato per creare il collegamento tra Swift e i file di intestazione delle Classi Objective-C

Infine, essendo la libreria scritta in Swift 4.0, dovrai specificare la versione di Swift da utilizzare (la 3.2 è la versione predefinita).
Fai clic sulla radice del progetto (non HotDog), seleziona la scheda "Impostazioni build", quindi in fondo, cambia la versione della lingua Swift da utilizzare.

Importa il modello CoreML nel progetto

Prima di passare alla parte di programmazione, non resta che importare il nostro modello di classificazione delle immagini nel progetto notHotDog.
Trascina e rilascia il modello Classifier.mlmodel e rinominalo notHotDog.mlmodelc (no, non è un errore di battitura)

CoreML non funziona direttamente con i file _.mlmodel, devi prima tradurli in _.mlmodelc (c per compilato), ma il nostro script Python se ne è già occupato. (vedi ultima riga del file train_model.py)

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

Consenti l'accesso alla fotocamera

Nel file Info.plist, fai clic sul piccolo più a destra di ciascuna voce e aggiungi "Privacy - Descrizione utilizzo fotocamera" come mostrato di seguito

Questo è tutto per l'installazione! Resta solo da implementare tutto questo.
codice gif

Implementa il codice

La prima cosa da fare è importare la libreria immagine reattiva-nativa-core-ml nel progetto. Per questo esempio, tutto il codice sarà nel file App.js

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

Quindi, sostituisci l'intero metodo render() con il seguente:

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>
    );
  }

Il metodo suClassificazione ci permette di ricevere aggiornamenti quando un nuovo oggetto è stato classificato. Restituisce i seguenti dati:

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

Non ci resta che implementare il metodo suClassificazione chi è responsabile di trovare la migliore classifica.

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
      });
    }
  }

Sulla base dei dati precedenti, lo sarà bestMatch

{
identifier: "hotdog",
confidence: 0.87
}

Ecco il codice 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
  }
});

Tutto quello che devi fare è eseguire il codice sul tuo iPhone (la fotocamera non funzionerà sul simulatore).
Se hai fatto tutto bene, l'app ti chiederà il permesso di accedere alla tua fotocamera e sarai in grado di distinguere un hotdog dal bassotto del tuo vicino.
Grazie per avermi letto. Se l'articolo ti è piaciuto, non esitare a condividerlo sui social network!
Articolo scritto da Geremia Zarca.