Пошаговое руководство по применению модели TensorFlow, созданной на Python, к серверной части Node.Js (Express).

Введение

В нынешнюю эпоху мы можем найти множество платформ, веб-сайтов и приложений, которые реализуют машинное обучение для улучшения своих бизнес-процессов и опыта. TensorFlow — это известная платформа с открытым исходным кодом, которая широко используется для разработки модели машинного обучения. Его также можно интегрировать во многие платформы с различными языками, например Python, JavaScript, Java, C++ и т. д.

С другой стороны, Express.Js — это фреймворк на основе JavaScript, который широко используется для создания серверных сервисов. Несмотря на то, что Tensorflow может быть построен на JavaScript с помощью Tensorflow.Js, Python, похоже, имеет больше утилит и удобных инструментов и функций для создания модели ML, таких как NumPy, Pandas и другие материалы, которые могут быть полезны разработчикам ML для проведения своих исследований и эксперименты по построению самой модели. Затем можно ли реализовать модель машинного обучения, созданную с помощью Tensorflow (на Python), для серверной службы в Express? Ответ абсолютно да.

TensorFlow предлагает различные форматы того, как модель машинного обучения, которую вы хотите сохранить, и TensorFlow.js может использовать базовый формат SavedModel, формат, который вы можете легко получить, выполнив model.save('folder_name_of_saved_model'), в результате чего появится папка, содержащая несколько .pb файлов; Или вы можете преобразовать модель после ее сохранения в формат TensorFlow.js, в результате чего появится папка, содержащая файл JSON и несколько файлов .bin.

Однако, что касается этого поста в блоге TensorFlow, мы видим, что служба, которая напрямую применяет SavedModel, улучшила (ускорила) время вывода для предсказания по сравнению с использованием модели Converted TensorFlow.js, независимо от того, какая версия tfjs-node использовался (ЦП и ГП). Сравнение производительности показано на изображении ниже.

Поэтому в этой статье мы будем использовать SavedModel.

Подготовка материалов

В этой статье я подготовил SavedModel классификатора жестов камень-ножницы-бумага по этой ссылке. Модель будет создавать массив вероятностей для каждого класса в формате:

[[paper_prob, rock_prob, scissors_prob]]

Вот изображение каменного знака из набора данных RPS Лоуренса Морони, которое использовалось для пробного теста SavedModel.

Прежде чем перейти к следующим шагам, убедитесь, что на вашем устройстве уже установлены NodeJS и NPM, и вы готовы получить необходимые пакеты. Вы можете проверить, готовы ли они или нет, запустив npm -v и node -v в своем терминале, PowerShell, командной строке или другой оболочке (после этого я бы назвал ее просто оболочкой). Если вы не установили Node с его дополнительными функциями (node-gyp), если вы используете Windows, вам может потребоваться переустановить Node LTS из его графического интерфейса с принятием дополнительной установки или прочитать эту ветку stackoverflow.

Во-первых, нам нужно создать приложение express.js. Запустите эту строку в своей оболочке, чтобы создать шаблон нашей серверной службы Express. Эта команда создаст приложение express.js с именем imageRecogAPI с Pug в качестве движка шаблонов и создаст папку с этим именем, содержащую исходный код для нашей серверной службы.

npx express-generator --view=pug imageRecogAPI

Затем запустите эту команду в блоке кода ниже в вашей оболочке, чтобы установить полные зависимости для этого проекта. Флаг --legacy-peer-deps — это просто мера предосторожности для конфликтов зависимостей между пакетами на тот случай, если какой-либо пакет имеет другой пакет, указанный ниже, но с его более старой версией. Вы также можете добавить флаг --verbose после флага --legacy-peer-deps, если хотите видеть ход установки (на случай, если установка застряла).

npm install @tensorflow/tfjs-node cookie-parser cors multer debug get-image-data jimp morgan express pug --save --legacy-peer-deps

Если вы когда-нибудь столкнулись с ошибкой при установке, вы можете запустить этот скрипт ниже, или если вы застряли при установке, нажмите Ctrl+ C , затем запустите этот скрипт ниже. После этого повторно запустите команду npm install выше. Если вы на самом деле работаете через прокси, возможно, вы сможете решить проблему с помощью этой статьи.

npm cache clear --force


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

imageRecogAPI/
├── node_modules/
├── bin/
│   └── www
├── public/
│   ├── images/
│   ├── javascripts/
│   └── stylesheets/
├── routes/
│   ├── index.js
│   └── users.js
├── views/
│   ├── error.pug
│   ├── index.pug
│   └── layout.pug
├── SavedModel/
│   ├── variables/
│   ├── keras_metadata.pb
│   └── saved_model.pb
├── app.js
├── package.json
└── package-lock.json

Развитие сервиса

Настройка app.js и маршрута

Приступим к разработке. Самое важное, что мы уже видим в структуре проекта, это app.js . Ничего не изменяя, вы уже должны получить этот шаблон:

Если вы хотите изменить ПОРТ вашего приложения, вы можете добавить эти строки над module.export в свой app.js . В приведенном ниже коде портом по умолчанию будет 9000. Вы можете просто изменить значение или добавить файл .env, а затем написать PORT=9000 (если вы хотите, чтобы служба работала на порту 9000).

const PORT = process.env.PORT || 9000;
app.listen(PORT);
console.log(`Running server at http://localhost:${PORT}`);

Затем запустите приложение с помощью команды npm run start, затем откройте браузер и перейдите к http://localhost:9000, вы увидите стандартную страницу приветствия Express.

После этого проверяем маршруты в app.js, там уже 2 роутера ( / и /users ). Вы также можете попробовать получить доступ к http://localhost:9000/users. Если вы прочтете вышеизложенное, то увидите, как определяются и используются маршруты. Затем добавьте выделенные жирным шрифтом строки кода снизу в свой app.js .

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users'); 
var predictionRouter = require('./routes/predict');
...
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/predict', predictionRouter);

Поэтому мы создадим свой собственный маршрут, создав новый файл predict.js внутри каталога routes/ и скопировав в него приведенный ниже код.

Вот объяснение кода выше:

  1. Во-первых, мы импортируем необходимые пакеты, то есть express и multer. Что касается controller, мы создадим его позже, поскольку он предназначен для основного процесса распознавания изображений с использованием модели ML.
  2. Затем мы объявляем имя файла, которое вы хотите использовать. Это имя файла должно совпадать с именем, которое вы будете использовать в контроллере.
  3. После этого мы настроили дисковое хранилище multer и проверку/фильтр файлов для обработки загруженного изображения. Помните, в пункте назначения мы установили загруженные изображения для сохранения в папку images/ из корня проекта.
  4. Наконец, мы настраиваем внутренний маршрутизатор / с префиксом /predict. Поставьте туда мультер, проверьте тип файла и наличие файла, так как это должно быть обязательным полем в запросе multipart/form-data. Затем передайте их все контроллеру, если запрос соответствует требованиям.

Создайте контроллер

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

Это объяснение из приведенного выше кода:

  1. Сначала импортируем все пакеты (как всегда).
  2. Мы просто ставим весь процесс и экспортируем их все сразу.
  3. В экспортируемой функции есть две основные функции: loadModel() и image(), которые будут объяснены ниже.

ФункцияloadModel() выполняет следующие действия:

  1. Загрузка SavedModel с помощью await tf.node.loadSavedModel()
  2. Сделайте прогноз и получите результат с помощью await model.predict().data()
  3. Превратите результат прогноза в массив, а затем отправьте его в качестве ответа.

Функция image() выполняет следующие шаги:

  1. Прочитайте загруженное изображение, которое будет предсказано.
  2. Преобразуйте изображение в тензоры, чтобы модель могла предсказать его.
  3. Поскольку модель была построена для чтения изображения с формой (None, 150, 150, 3), нам также нужно изменить размер этого тензора на эту форму на resizeNearestNeighbor(), чтобы изменить размер изображения до 150 x 150, и на expandDims(), чтобы добавить одно измерение. Поскольку изображение уже было в RGB, нам не нужно беспокоиться о 3 в форме.
  4. После этого нормализуем тензоры изображения, разделив их на 255.
  5. Затем мы вызываем loadModel() и удаляем файл изображения после завершения предсказания.

Затем перейдите в свою оболочку, запустите npm run start. Попробуйте свежеприготовленный сервис с Postman. В раскрывающемся списке выберите File в столбце Ключ. Если вы сделали все шаги с самого начала правильно, вы должны получить это.

Однако вы можете улучшить отдачу прогнозов с помощью собственного стиля. Например, если вы просто хотите получить имя класса и вероятность того, что имеет наибольшую вероятность, вы можете использовать следующий прием. Вначале мы знаем, что массив прогнозов будет иметь значения, расположенные как [paper, rock, scissors] . Используя собственные методы Javascript для массива, мы можем легко получить его.

Вернемся к PredictionController , у нас есть строка:

predictions = Array.from(predictions);

Мы можем изменить его на

predictions = Array.from(predictions)
                   // Construct
                .map((prob, idx) => {
                  var classes = ['paper', 'rock', 'scissors'];
                  return {class: classes[idx], probability: prob};
                })
                   // Sort Descending, Get the highest one                
                .sort((a, b) => b.probability - a.probability)[0];

Затем, мы делаем это.

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

Заключение

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



Об авторе

В настоящее время Дхана работает над оптимизацией бизнес-процессов, создавая или расширяя услуги инженера-программиста в индонезийском банке.

Помимо разработки программного обеспечения, Дхана любит узнавать и делиться информацией о машинном обучении и уже сертифицирована как разработчик TensorFlow с 2021 года. Наконец, пожалуйста, свяжитесь с Дхана в Medium и LinkedIn.



🔵 Стать писателем