Si vous êtes comme moi, et que vous avez toujours rêvé de développer une application capable de différencier un hotdog du teckel de votre voisine grâce à votre Iphone, ce tutoriel est pour vous. Nous utiliserons pour ce faire React-Native, et le machine learning. C’est parti !
Les solutions de Machine Learning sont depuis longtemps disponibles dans le cloud via des API, mais elles demandaient une connexion internet et leur temps de traitement pouvait s’avérer long et coûteux à la fois.
Avec la sortie d’iOS 11, Apple a mis à disposition des développeurs sa librairie de Machine Learning, CoreML. Désormais, il n’est plus nécessaire d’avoir un serveur puissant pour traiter les requêtes ou faire appel à une API tierce. CoreML s’occupe de tout avec la puissance de calcul de votre smartphone.
Vous êtes curieux de savoir comment l’intégrer dans vos applications ? C’est plus simple que ce que vous pourriez penser.
Prenons comme exemple, la célèbre application parodique Not Hotdog, découverte dans la série Silicon Valley, qui, lorsque l’utilisateur pointe son smartphone vers un objet, lui dit instantanément si ce dernier regarde un hotdog ou non.
Ce que vous allez apprendre dans cette partie
- Installer votre environnement
- Collecter des données
- Créer votre modèle de classification d’image avec Turi Create
- Reconnaître un hotdog grâce à la caméra de votre iPhone
Les prérequis
- macOS 10.12+
- ou Linux (avec glibc 2.12+)
- ou Windows 10 (via WSL)
-
Python 2.7, 3.5 ou 3.6
-
une architecture x86_64
-
Xcode 9
- iOS 11+
Qu’est-ce que Turi Create ?
Il s’agit d’un outil qui « simplifie le développement de modèles de machine learning personnalisés », pouvant être ensuite exploités dans des applications utilisant la librairie CoreML.
Turi Create se base sur le framework de Deep Learning MXNet d’Apache
Turi Create met à disposition des développeurs une technologie souple pour classifier des images, détecter des objets, concevoir des systèmes de recommandations, … etc.
L’outil est extrêmement simple d’utilisation, flexible et rapide.
Son installation
Comme pour beaucoup d’outils de Machine Learning, python est le langage utilisé. Mais ne vous en faites pas, le code est très simple à comprendre.
Il est recommandé d’utiliser un environnement virtuel, virtualenv, en entrant la commande
pip install virtualenv
Si vous n’avez pas pip, le gestionnaire de paquets de Python, vous pouvez l’installer grâce à Homebrew en entrant la commande
brew install pip
Puis,
// Créer un environnement virtuel Python cd ~ virtualenv venv // Activer votre environnement virtuel source ~/venv/bin/activate // Installer Turi Create pip install -U turicreate
Collecter des données
Avant de pouvoir entraîner un modèle, il nous faut des données.
Ces données, on peut les trouver sur le site ImageNet qui est une très large base de données d’images, avec plus de 14 millions de résultats.
Pour notre projet, nous avons besoin de deux catégories d’images: Hotdog et… Not Hotdog.
Voici le lien pour la première catégorie: http://www.image-net.org/synset?wnid=n07697537.
On peut également récupérer tous les liens en utilisant l’API publique, via le bouton Download dans l’onglet Downloads
http://www.image-net.org/api/text/imagenet.synset.geturls?wnid=n07697537
Utilisation de turicreate-easy-scripts
Vous pourrez retrouver sur le repository turicreate-easy-scripts un ensemble de scripts qui vous faciliteront la vie.
Ainsi, après avoir cloner le repos et installé les dépendances du dossier download-image
:
cd download-images npm install
Vous pourrez executer la commande :
node imagenet-downloader.js http://www.image-net.org/api/text/imagenet.synset.geturls?wnid=n07697537 hotdog
Et obtenir un dossier rempli d’images de hotdogs.
Il ne reste plus qu’à faire la même chose pour Not Hotdog. Choisissez donc la/les catégories qui vous plaisent le plus et catégorisez-les comme not-hotdog
node imagenet-downloader.js http://image-net.org/api/text/imagenet.synset.geturls?wnid=n00021939 not-hotdog
Entraîner le modèle
Une fois les images téléchargées et catégorisées, il ne reste plus qu’à entraîner le modèle de classification.
Pour ce faire, vous pouvez utiliser le script python mis à disposition dans le repository téléchargé précédemment
cd train-model python train-model.py
Vous obtiendrez au bout d’une dizaine de minutes (ou plus selon le nombre d’images à traiter) un fichier Classifier.mlmodel
que l’on peut désormais pouvoir exploiter.
Créer un projet React-Native
Tout d’abord, il faudra créer un nouveau projet React-Native.
Ouvrez votre terminal, naviguez dans votre dossier de projets et entrez la commande suivante :
react-native init notHotDog (ou tout autre nom)
Au bout de quelques minutes, tout sera installé et vous serez prêt à passer à la suite.
Installer la librairie CoreML
Nous allons utiliser la librairie react-native-core-ml-image
npm install --save react-native-core-ml-image react-native link
Allez dans votre projet, puis dans le dossier “ios” et double-cliquez sur le fichier notHotDog.xcodeproj pour l’ouvrir dans Xcode
Configurer le projet
Par défaut, les projets en React-Native sont configurés pour utiliser principalement Objective-C. La librairie react-native-core-ml-image étant écrite en Swift, il va falloir changer quelques paramètres dans le projet
Tout d’abord, il va falloir ajouter un fichier Swift au projet
Le nom importe peu, il ne sera de toute façon pas utilisé. Un message apparaît alors vous proposant de créer un “Objective-C Bridging Header” : c’est le fichier qui sert à faire le lien entre Swift et les fichiers entête des Classes Objective-C
Enfin, la librairie étant écrite en Swift 4.0, il va falloir spécifier la version de Swift à utiliser (la 3.2 étant la version par défaut).
Cliquez sur la racine du projet (notHotDog), séléctionnez l’onglet “Build Settings”, puis tout en bas, changez la version du langage Swift à utiliser.
Importer le modèle CoreML dans le projet
Avant de passer à la partie programmation, il ne reste plus qu’à importer notre modèle de classification d’images dans le projet notHotDog.
Glissez-déposez le modèle Classifier.mlmodel
et renommez-le notHotDog.mlmodelc
(non, ce n’est pas une faute de frappe)
CoreML ne fonctionne pas directement avec les fichiers _.mlmodel, il faut d’abord les traduire en _.mlmodelc (c pour compiled), mais notre script Python s’en est déjà occupé. (cf. dernière ligne du fichier train_model.py
)
# Export for use in Core ML model.export_coreml('Classifier.mlmodel')
Autoriser l’accès à la caméra
Dans le fichier Info.plist, cliquez sur le petit plus à la droite de chaque entrée et ajoutez “Privacy – Camera Usage Description” comme montré ci-dessous
C’est tout pour la configuration ! Il ne reste plus qu’à implémenter tout cela.
Implémenter le code
La première chose à faire est d’importer la librairie react-native-core-ml-image dans le projet. Pour cet exemple, tout le code se situera dans le fichier App.js
import CoreMLImage from 'react-native-core-ml-image'
Ensuite, remplacez toute la méthode render() par ce qui vient ci-après :
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> ); }
La méthode onClassification nous permet de recevoir des updates quand un nouvel objet a été classifié. Il renvoie les données suivantes :
[ { identifier: "hotdog", confidence: 0.87 }, { identifier: "not-hotdog", confidence: 0.4 } ]
Nous n’avons plus qu’à implémenter la méthode onClassification qui se charge de trouver la meilleure classification.
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 }); } }
Si l’on se base sur les données précédentes, alors bestMatch vaudra
{ identifier: "hotdog", confidence: 0.87 }
Voici le code complet:
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 } });
Il ne vous reste plus qu’à éxecuter le code sur votre iPhone (la caméra ne fonctionnera pas sur le simulateur).
Si vous avez tout bien fait, l’app vous demandera la permission d’accéder à votre appareil photo et vous pourrez alors distinguer un hotdog du teckel de votre voisine.
Merci de m’avoir lu. Si l’article vous a plu, n’hésitez pas à le partager sur les réseaux sociaux !
Article écrit par Jérémie Zarca.