Машинне навчання на iOS з CoreML і React-Native

Якщо ви подібні до мене, і ви завжди мріяли розробити програму, здатну відрізнити хот-дог від такс вашого сусіда за допомогою вашого iPhone, цей посібник для вас. Для цього ми будемо використовувати React-Native і машинне навчання. Ходімо !
Рішення машинного навчання вже давно доступні в хмарі через API, але вони вимагають підключення до Інтернету, а їх обробка може займати багато часу та дорого.
З випуском iOS 11 Apple зробила свою бібліотеку машинного навчання CoreML доступною для розробників. Тепер більше не потрібно мати потужний сервер для обробки запитів або виклику стороннього API. CoreML подбає про все за допомогою обчислювальної потужності вашого смартфона.
Вам цікаво, як інтегрувати його у свої програми? Це простіше, ніж ви думаєте.
Візьмемо для прикладу відомий пародійний додаток Не Хотдог, виявлені в серії Силіконова долина, який, коли користувач наводить свій смартфон на об’єкт, миттєво повідомляє йому, дивиться останній на хот-дог чи ні.
Не хот-дог

Про що ви дізнаєтеся в цій частині

  • Встановіть своє середовище
  • Збирати дані
  • Створіть свою модель класифікації зображень за допомогою Turi Create
  • Розпізнайте хот-дог за допомогою камери вашого iPhone

Передумови

  • macOS 10.12+
  • або Linux (з glibc 2.12+)
  • або Windows 10 (через WSL)

  • Python 2.7, 3.5 або 3.6

  • архітектура x86_64

  • Xcode 9

  • iOS11+

Що таке Turi Create?

Це інструмент, який «спрощує розробку користувацьких моделей машинного навчання», які потім можна використовувати в додатках із використанням бібліотеки CoreML.
Turi Create засновано на фреймворку Deep Learning MXNet Apache
Turi Create надає розробникам гнучку технологію для класифікації зображень, виявлення об’єктів, систем рекомендацій щодо дизайну тощо.
Інструмент надзвичайно простий у використанні, гнучкий та швидкий.

Його встановлення

Як і багато інструментів машинного навчання, пітон це мова, яка використовується. Але не хвилюйтеся, код дуже простий для розуміння.
Рекомендується використовувати віртуальне середовище, virtualenv, ввівши команду

pip install virtualenv

Якщо у вас немає pip, менеджера пакетів Python, ви можете встановити його за допомогою Homebrew ввівши команду

brew install pip

то,

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

Збирати дані

Перш ніж ми зможемо навчити модель, нам потрібні дані.
Ці дані можна знайти на сайті IMAGEnet це дуже велика база даних зображень із понад 14 мільйонами результатів.
Для нашого проекту нам потрібні дві категорії зображень: хот-дог і… не хот-дог.
Ось посилання для першої категорії: http://www.image-net.org/synset?wnid=n07697537.

Ви також можете отримати всі посилання за допомогою публічного API за допомогою кнопки Завантажити на вкладці Завантаження

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

Використання скриптів turicreate-easy

Ви можете знайти в репозитарії turicreate-easy-scripts набір сценаріїв, які полегшать вам життя.
Тому після клонування репозиторій та встановлення залежностей папки download-image :

cd download-images
npm install

Ви можете запустити команду:

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

І отримати папку, повну фотографій хот-догів.
Все, що залишилося, це зробити те ж саме для Not Hotdog. Тому виберіть категорію(и), яка(и) вам найбільше подобається, і віднесіть їх до категорії не-хот-догів

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

Тренуйте модель

Після того, як зображення були завантажені та класифіковані, залишається лише навчити модель класифікації.
Для цього ви можете використовувати сценарій Python, доступний у сховищі, завантаженому раніше

cd train-model
python train-model.py


Приблизно через десять хвилин (або більше, залежно від кількості зображень, які потрібно обробити) ви отримаєте файл Classifier.mlmodel що ми зараз можемо використовувати.
gif мл

Створіть проект React-Native

Спочатку вам потрібно буде створити новий проект React-Native.
Відкрийте свій термінал, перейдіть до папки ваших проектів і введіть таку команду:

react-native init notHotDog (ou tout autre nom)

Через кілька хвилин все буде встановлено, і ви будете готові рухатися далі.

Встановіть бібліотеку CoreML

Будемо користуватися бібліотекою react-native-core-ml-image

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

Перейдіть до свого проекту, потім до папки «ios» і двічі клацніть файл notHotDog.xcodeproj, щоб відкрити його в Xcode

Налаштуйте проект

За замовчуванням проекти React-Native налаштовані на використання в основному Objective-C. Книжковий магазин react-native-core-ml-image будучи написаним на Swift, необхідно буде змінити деякі параметри в проекті
Перш за все, нам потрібно буде додати файл Swift до проекту


Назва не має значення, вона все одно не буде використовуватися. Після цього з’являється повідомлення із пропозицією створити «заголовок Objective-C Bridging Header»: це файл, який використовується для встановлення зв’язку між Swift і файлами заголовків класів Objective-C.

Нарешті, бібліотека написана на Swift 4.0, вам потрібно буде вказати версію Swift для використання (3.2 є версією за замовчуванням).
Клацніть на корені проекту (notHotDog), виберіть вкладку «Налаштування збірки», а потім у самому низу змініть версію мови Swift для використання.

Імпортуйте модель CoreML в проект

Перш ніж перейти до частини програмування, залишається лише імпортувати нашу модель класифікації зображень у проект notHotDog.
Перетягніть шаблон Classifier.mlmodel і перейменувати його notHotDog.mlmodelc (ні, це не опечатка)

CoreML не працює безпосередньо з файлами _.mlmodel, вам потрібно спочатку перекласти їх у _.mlmodelc (c для компіляції), але наш скрипт Python вже подбав про це. (див. останній рядок файлу train_model.py)

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

Дозволити доступ до камери

У файлі Info.plist натисніть маленький плюсик праворуч від кожного запису та додайте «Конфіденційність – опис використання камери», як показано нижче.

Ось і все для налаштування! Залишилося лише все це реалізувати.
gif-код

Впровадити код

Перше, що потрібно зробити, це імпортувати бібліотеку react-native-core-ml-image в проекті. Для цього прикладу весь код буде у файлі App.js

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

Далі замініть весь метод render() на такий:

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

Метод прокласифікацію дозволяє нам отримувати оновлення, коли новий об’єкт був класифікований. Він повертає такі дані:

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

Нам залишається лише реалізувати метод прокласифікацію хто відповідає за пошук найкращої класифікації.

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

На основі попередніх даних буде bestMatch

{
identifier: "hotdog",
confidence: 0.87
}

Ось повний код:

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

Все, що вам потрібно зробити, це запустити код на своєму iPhone (камера не працюватиме на симуляторі).
Якщо ви все зробили правильно, програма запитає у вас дозвіл на доступ до камери, і ви зможете відрізнити хот-дог від такси вашого сусіда.
Дякую, що читаєте мене. Якщо вам сподобалася стаття, не соромтеся поділіться нею в соціальних мережах!
Стаття написана Єремія Зарка.