Машинное обучение для фронтенд-разработчиков с Tensorflow.js

Опубликовано: 2022-03-10
Краткое резюме ↬ Использование JavaScript и таких фреймворков, как Tensorflow.js, — отличный способ начать работу и узнать больше о машинном обучении. В этой статье Чарли Джерард описывает три основные функции, доступные в настоящее время при использовании Tensorflow.js, и проливает свет на ограничения использования машинного обучения во внешнем интерфейсе.

Часто кажется, что машинное обучение принадлежит специалистам по данным и разработчикам Python. Однако за последние пару лет были созданы фреймворки с открытым исходным кодом, чтобы сделать его более доступным на разных языках программирования, включая JavaScript. В этой статье мы будем использовать Tensorflow.js для изучения различных возможностей использования машинного обучения в браузере на нескольких примерах проектов.

Что такое машинное обучение?

Прежде чем мы начнем углубляться в код, давайте кратко поговорим о том, что такое машинное обучение, а также о некоторых основных понятиях и терминологии.

Определение

Распространенное определение состоит в том, что это способность компьютеров учиться на данных без явного программирования.

Если мы сравним его с традиционным программированием, это означает, что мы позволяем компьютерам выявлять закономерности в данных и генерировать прогнозы без необходимости указывать им, что именно искать.

Возьмем пример обнаружения мошенничества. Не существует установленных критериев, позволяющих определить, что делает транзакцию мошеннической, а что нет; мошеннические действия могут совершаться в любой стране, на любой счет, в отношении любого клиента, в любое время и так далее. Отследить все это вручную практически невозможно.

Однако, используя предыдущие данные о мошеннических расходах, собранные за многие годы, мы можем обучить алгоритм машинного обучения понимать закономерности в этих данных, чтобы сгенерировать модель, которая может учитывать любую новую транзакцию и предсказывать вероятность того, является ли она мошенничеством или нет, без говоря ему, что именно искать.

Еще после прыжка! Продолжить чтение ниже ↓

Основные концепции

Чтобы понять следующие примеры кода, нам нужно сначала рассмотреть несколько общих терминов.

Модель

Когда вы обучаете алгоритм машинного обучения с набором данных, модель является результатом этого процесса обучения. Это немного похоже на функцию, которая принимает новые данные на вход и выдает прогноз на выходе.

Этикетки и особенности

Метки и функции относятся к данным, которые вы передаете алгоритму в процессе обучения.

Метка представляет собой то, как вы бы классифицировали каждую запись в своем наборе данных и как бы вы ее пометили. Например, если бы наш набор данных был файлом CSV с описанием разных животных, наши метки могли бы быть такими словами, как «кошка», «собака» или «змея» (в зависимости от того, что представляет каждое животное).

С другой стороны, функции — это характеристики каждой записи в вашем наборе данных. Например, для наших животных это могут быть такие вещи, как «бакенбарды, мяуканье», «игривое, лает», «рептилия, безудержная» и так далее.

Используя это, алгоритм машинного обучения сможет найти некоторую корреляцию между функциями и их меткой, которую он будет использовать для будущих прогнозов.

Нейронные сети

Нейронные сети — это набор алгоритмов машинного обучения, которые пытаются имитировать работу мозга, используя слои искусственных нейронов.

Нам не нужно подробно рассказывать о том, как они работают в этой статье, но если вы хотите узнать больше, вот действительно хорошее видео:

Теперь, когда мы определили несколько терминов, обычно используемых в машинном обучении, давайте поговорим о том, что можно сделать с помощью JavaScript и фреймворка Tensorflow.js.

Функции

На данный момент доступны три функции:

  1. Используя предварительно обученную модель,
  2. Трансферное обучение,
  3. Определение, запуск и использование собственной модели.

Начнем с самого простого.

1. Использование предварительно обученной модели

В зависимости от проблемы, которую вы пытаетесь решить, может быть модель, уже обученная с определенным набором данных и для определенной цели, которую вы можете использовать и импортировать в свой код.

Например, предположим, что мы создаем веб-сайт, чтобы предсказать, является ли изображение изображением кошки. Популярная модель классификации изображений называется MobileNet и доступна в виде предварительно обученной модели с Tensorflow.js.

Код для этого будет выглядеть примерно так:

 <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Cat detection</title> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]"> </script> <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/[email protected]"> </script> </head> <body> <img alt="cat laying down" src="cat.jpeg"/> <script> const img = document.getElementById('image'); const predictImage = async () => { console.log("Model loading..."); const model = await mobilenet.load(); console.log("Model is loaded!") const predictions = await model.classify(img); console.log('Predictions: ', predictions); } predictImage(); </script> </body> </html>

Начнем с импорта Tensorflow.js и модели MobileNet в заголовок нашего HTML:

 <script src="https://cdnjs.cloudflare.com/ajax/libs/tensorflow/1.0.1/tf.js"> </script> <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/[email protected]"> </script>

Затем внутри тела у нас есть элемент изображения, который будет использоваться для прогнозов:

 <img alt="cat laying down" src="cat.jpeg"/>

И, наконец, внутри тега script у нас есть код JavaScript, который загружает предварительно обученную модель MobileNet и классифицирует изображение, найденное в теге image . Он возвращает массив из 3 прогнозов, упорядоченных по показателю вероятности (первый элемент является лучшим прогнозом).

 const predictImage = async () => { console.log("Model loading..."); const model = await mobilenet.load(); console.log("Model is loaded!") const predictions = await model.classify(img); console.log('Predictions: ', predictions); } predictImage();

Вот и все! Вот как вы можете использовать предварительно обученную модель в браузере с Tensorflow.js!

Примечание . Если вы хотите посмотреть, что еще может классифицировать модель MobileNet, вы можете найти список различных классов, доступных на Github.

Важно знать, что загрузка предварительно обученной модели в браузере может занять некоторое время (иногда до 10 секунд), поэтому вы, вероятно, захотите предварительно загрузить или адаптировать свой интерфейс, чтобы это не влияло на пользователей.

Если вы предпочитаете использовать Tensorflow.js в качестве модуля NPM, вы можете сделать это, импортировав модуль следующим образом:

 import * as mobilenet from '@tensorflow-models/mobilenet';

Не стесняйтесь поиграть с этим примером в CodeSandbox.

Теперь, когда мы увидели, как использовать предварительно обученную модель, давайте рассмотрим вторую доступную функцию: перенос обучения.

2. Передача обучения

Трансферное обучение — это возможность комбинировать предварительно обученную модель с пользовательскими обучающими данными. Это означает, что вы можете использовать функциональность модели и добавлять свои собственные образцы, не создавая все с нуля.

Например, алгоритм был обучен на тысячах изображений для создания модели классификации изображений, и вместо того, чтобы создавать свою собственную, трансферное обучение позволяет вам комбинировать новые пользовательские образцы изображений с предварительно обученной моделью для создания нового классификатора изображений. Эта функция позволяет очень быстро и легко создать более настраиваемый классификатор.

Чтобы показать пример того, как это будет выглядеть в коде, давайте изменим наш предыдущий пример и изменим его, чтобы мы могли классифицировать новые изображения.

Примечание . Конечным результатом является приведенный ниже эксперимент, который вы можете попробовать здесь.

(Живое демо) (Большой превью)

Ниже приведены несколько примеров кода наиболее важной части этой установки, но если вам нужно взглянуть на весь код, вы можете найти его в этой тестовой среде CodeSandbox.

Нам все еще нужно начать с импорта Tensorflow.js и MobileNet, но на этот раз нам также нужно добавить классификатор KNN (k-ближайший сосед):

 <!-- Load TensorFlow.js --> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script> <!-- Load MobileNet --> <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet"></script> <!-- Load KNN Classifier --> <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/knn-classifier"></script>

Причина, по которой нам нужен классификатор, заключается в том, что (вместо использования только модуля MobileNet) мы добавляем пользовательские образцы, которые он никогда раньше не видел, поэтому классификатор KNN позволит нам объединить все вместе и выполнить прогнозы на объединенных данных.

Затем мы можем заменить изображение кота тегом video , чтобы использовать изображения с камеры.

 <video autoplay width="227" height="227"></video>

Наконец, нам нужно добавить на страницу несколько кнопок, которые мы будем использовать в качестве меток для записи некоторых видеосэмплов и запуска прогнозов.

 <section> <button class="button">Left</button> <button class="button">Right</button> <button class="test-predictions">Test</button> </section>

Теперь давайте перейдем к файлу JavaScript, где мы начнем с настройки нескольких важных переменных:

 // Number of classes to classify const NUM_CLASSES = 2; // Labels for our classes const classes = ["Left", "Right"]; // Webcam Image size. Must be 227. const IMAGE_SIZE = 227; // K value for KNN const TOPK = 10; const video = document.getElementById("webcam");

В этом конкретном примере мы хотим иметь возможность классифицировать ввод с веб-камеры между наклоном головы влево или вправо, поэтому нам нужны два класса, помеченные как left и right .

Размер изображения, равный 227, соответствует размеру видеоэлемента в пикселях. Судя по примерам Tensorflow.js, для этого значения необходимо установить значение 227, чтобы оно соответствовало формату данных, с которыми обучалась модель MobileNet. Чтобы он мог классифицировать наши новые данные, последние должны соответствовать тому же формату.

Если вам действительно нужно, чтобы он был больше, это возможно, но вам придется преобразовать и изменить размер данных, прежде чем подавать их в классификатор KNN.

Затем мы устанавливаем значение K равным 10. Значение K в алгоритме KNN важно, поскольку оно представляет количество экземпляров, которые мы учитываем при определении класса нашего нового ввода.

В этом случае значение 10 означает, что при прогнозировании метки для некоторых новых данных мы будем смотреть на 10 ближайших соседей из обучающих данных, чтобы определить, как классифицировать наши новые входные данные.

Наконец, мы получаем элемент video . Для логики начнем с загрузки модели и классификатора:

 async load() { const knn = knnClassifier.create(); const mobilenetModule = await mobilenet.load(); console.log("model loaded"); }

Затем давайте получим доступ к видеопотоку:

 navigator.mediaDevices .getUserMedia({ video: true, audio: false }) .then(stream => { video.srcObject = stream; video.width = IMAGE_SIZE; video.height = IMAGE_SIZE; });

После этого давайте настроим несколько событий кнопок для записи наших демонстрационных данных:

 setupButtonEvents() { for (let i = 0; i < NUM_CLASSES; i++) { let button = document.getElementsByClassName("button")[i]; button.onmousedown = () => { this.training = i; this.recordSamples = true; }; button.onmouseup = () => (this.training = -1); } }

Давайте напишем нашу функцию, которая будет брать образцы изображений с веб-камеры, переформатировать их и объединять с модулем MobileNet:

 // Get image data from video element const image = tf.browser.fromPixels(video); let logits; // 'conv_preds' is the logits activation of MobileNet. const infer = () => this.mobilenetModule.infer(image, "conv_preds"); // Train class if one of the buttons is held down if (this.training != -1) { logits = infer(); // Add current image to classifier this.knn.addExample(logits, this.training); }

И, наконец, когда мы собрали несколько изображений с веб-камеры, мы можем проверить наши прогнозы с помощью следующего кода:

 logits = infer(); const res = await this.knn.predictClass(logits, TOPK); const prediction = classes[res.classIndex];

И, наконец, вы можете избавиться от данных веб-камеры, так как они нам больше не нужны:

 // Dispose image when done image.dispose(); if (logits != null) { logits.dispose(); }

Еще раз, если вы хотите взглянуть на полный код, вы можете найти его в CodeSandbox, упомянутом ранее.

3. Обучение модели в браузере

Последняя функция — определение, обучение и запуск модели полностью в браузере. Чтобы проиллюстрировать это, мы создадим классический пример распознавания ирисов.

Для этого мы создадим нейронную сеть, которая сможет классифицировать ирисы по трем категориям: Setosa, Virginica и Versicolor на основе набора данных с открытым исходным кодом.

Прежде чем мы начнем, вот ссылка на живую демонстрацию и вот CodeSandbox, если вы хотите поиграть с полным кодом.

В основе каждого проекта машинного обучения лежит набор данных. Один из первых шагов, которые нам нужно предпринять, — это разделить этот набор данных на обучающий набор и тестовый набор.

Причина этого в том, что мы собираемся использовать наш обучающий набор для обучения нашего алгоритма и наш тестовый набор для проверки точности наших прогнозов, чтобы проверить, готова ли наша модель к использованию или ее нужно настроить.

Примечание . Чтобы упростить задачу, я уже разделил обучающий набор и тестовый набор на два файла JSON, которые вы можете найти в CodeSanbox.

Обучающий набор содержит 130 элементов, а тестовый набор — 14. Если вы посмотрите, как выглядят эти данные, вы увидите что-то вроде этого:

 { "sepal_length": 5.1, "sepal_width": 3.5, "petal_length": 1.4, "petal_width": 0.2, "species": "setosa" }

Мы видим четыре различных признака длины и ширины чашелистика и лепестка, а также метку вида.

Чтобы иметь возможность использовать это с Tensorflow.js, нам нужно преобразовать эти данные в формат, понятный фреймворку, в этом случае для обучающих данных это будет [130, 4] для 130 выборок с четырьмя функциями на радужная оболочка.

 import * as trainingSet from "training.json"; import * as testSet from "testing.json"; const trainingData = tf.tensor2d( trainingSet.map(item => [ item.sepal_length, item.sepal_width, item.petal_length, item.petal_width ]), [130, 4] ); const testData = tf.tensor2d( testSet.map(item => [ item.sepal_length, item.sepal_width, item.petal_length, item.petal_width ]), [14, 4] );

Далее нам нужно сформировать наши выходные данные:

 const output = tf.tensor2d(trainingSet.map(item => [ item.species === 'setosa' ? 1 : 0, item.species === 'virginica' ? 1 : 0, item.species === 'versicolor' ? 1 : 0 ]), [130,3])

Затем, когда наши данные готовы, мы можем перейти к созданию модели:

 const model = tf.sequential(); model.add(tf.layers.dense( { inputShape: 4, activation: 'sigmoid', units: 10 } )); model.add(tf.layers.dense( { inputShape: 10, units: 3, activation: 'softmax' } ));

В приведенном выше примере кода мы начинаем с создания экземпляра последовательной модели, добавляем входной и выходной слой.

Параметры, используемые внутри ( inputShape , activation и units ), выходят за рамки этого поста, поскольку они могут различаться в зависимости от создаваемой модели, типа используемых данных и т. д.

Как только наша модель будет готова, мы можем обучить ее с нашими данными:

 async function train_data(){ for(let i=0;i<15;i++){ const res = await model.fit(trainingData, outputData,{epochs: 40}); } } async function main() { await train_data(); model.predict(testSet).print(); }

Если это работает хорошо, вы можете начать заменять тестовые данные пользовательскими входными данными.

Как только мы вызовем нашу основную функцию, вывод прогноза будет выглядеть как один из этих трех вариантов:

 [1,0,0] // Setosa [0,1,0] // Virginica [0,0,1] // Versicolor

Предсказание возвращает массив из трех чисел, представляющих вероятность того, что данные принадлежат одному из трех классов. Число, ближайшее к 1, является самым высоким прогнозом.

Например, если результат классификации равен [0.0002, 0.9494, 0.0503] , второй элемент массива является самым высоким, поэтому модель предсказала, что новый вход, скорее всего, будет Virginica.

И это все для простой нейронной сети в Tensorflow.js!

Мы говорили только о небольшом наборе данных об ирисах, но если вы хотите перейти к большим наборам данных или работать с изображениями, шаги будут такими же:

  • Сбор данных;
  • Разделение между обучающим и тестовым набором;
  • Переформатирование данных, чтобы Tensorflow.js мог их понять;
  • Выбор вашего алгоритма;
  • Подгонка данных;
  • Прогнозирование.

Если вы хотите сохранить созданную модель, чтобы иметь возможность загрузить ее в другом приложении и предсказать новые данные, вы можете сделать это с помощью следующей строки:

 await model.save('file:///path/to/my-model'); // in Node.js

Примечание . Чтобы узнать больше о том, как сохранить модель, ознакомьтесь с этим ресурсом.

Ограничения

Вот и все! Мы только что рассмотрели три основные функции, доступные в настоящее время с использованием Tensorflow.js!

Прежде чем мы закончим, я думаю, важно кратко упомянуть некоторые ограничения использования машинного обучения во внешнем интерфейсе.

1. Производительность

Импорт предварительно обученной модели из внешнего источника может повлиять на производительность вашего приложения. Некоторые модели обнаружения объектов, например, имеют размер более 10 МБ, что значительно замедлит работу вашего сайта. Обязательно подумайте о своем пользовательском опыте и оптимизируйте загрузку ваших ресурсов, чтобы улучшить воспринимаемую производительность.

2. Качество входных данных

Если вы строите модель с нуля, вам придется собирать свои собственные данные или искать набор данных с открытым исходным кодом.

Прежде чем выполнять какую-либо обработку данных или пробовать различные алгоритмы, обязательно проверьте качество ваших входных данных. Например, если вы пытаетесь построить модель анализа настроений для распознавания эмоций в фрагментах текста, убедитесь, что данные, которые вы используете для обучения модели, точны и разнообразны. Если качество используемых данных низкое, результаты вашего обучения будут бесполезными.

3. Ответственность

Использование предварительно обученной модели с открытым исходным кодом может быть очень быстрым и легким. Однако это также означает, что вы не всегда знаете, как он был сгенерирован, из чего состоял набор данных или даже какой алгоритм использовался. Некоторые модели называются «черными ящиками», что означает, что вы на самом деле не знаете, как они предсказали определенный результат.

В зависимости от того, что вы пытаетесь построить, это может быть проблемой. Например, если вы используете модель машинного обучения, чтобы помочь определить вероятность того, что у кого-то есть рак на основе сканированных изображений, в случае ложноотрицательного результата (модель предсказывала, что у человека не было рака, когда он действительно был), есть может быть реальная юридическая ответственность, и вы должны быть в состоянии объяснить, почему модель сделала определенный прогноз.

Резюме

В заключение, использование JavaScript и таких фреймворков, как Tensorflow.js, — отличный способ начать работу и узнать больше о машинном обучении. Несмотря на то, что готовое к производству приложение, вероятно, должно быть построено на таком языке, как Python, JavaScript делает его действительно доступным для разработчиков, чтобы поиграть с различными функциями и лучше понять фундаментальные концепции, прежде чем в конечном итоге двигаться дальше и тратить время на изучение другого. язык.

В этом руководстве мы рассмотрели только то, что было возможно с помощью Tensorflow.js, однако экосистема других библиотек и инструментов растет. Также доступны более специализированные фреймворки, позволяющие исследовать использование машинного обучения в других областях, таких как музыка с Magenta.js, или предсказывать навигацию пользователя на веб-сайте с помощью Guess.js!

По мере того, как инструменты становятся все более производительными, возможности создания приложений с поддержкой машинного обучения на JavaScript, вероятно, будут становиться все более и более захватывающими, и сейчас самое время узнать об этом больше, поскольку сообщество прилагает усилия для того, чтобы сделать его доступным.

Дополнительные ресурсы

Если вы хотите узнать больше, вот несколько ресурсов:

Другие фреймворки и инструменты

  • мл5.js
  • мл.js
  • мозг.js
  • Keras.js
  • Поснет
  • Игровая площадка Tensorflow

Примеры, модели и наборы данных

  • Модели Tensorflow.js
  • Примеры Tensorflow.js
  • Наборы данных

Вдохновение

  • Обучаемая машина
  • эксперименты с ИИ
  • AIJS.rocks
  • Креативность

Спасибо за прочтение!