Пошаговое руководство по применению модели 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/
и скопировав в него приведенный ниже код.
Вот объяснение кода выше:
- Во-первых, мы импортируем необходимые пакеты, то есть
express
иmulter
. Что касаетсяcontroller
, мы создадим его позже, поскольку он предназначен для основного процесса распознавания изображений с использованием модели ML. - Затем мы объявляем имя файла, которое вы хотите использовать. Это имя файла должно совпадать с именем, которое вы будете использовать в контроллере.
- После этого мы настроили дисковое хранилище multer и проверку/фильтр файлов для обработки загруженного изображения. Помните, в пункте назначения мы установили загруженные изображения для сохранения в папку
images/
из корня проекта. - Наконец, мы настраиваем внутренний маршрутизатор
/
с префиксом/predict
. Поставьте туда мультер, проверьте тип файла и наличие файла, так как это должно быть обязательным полем в запросеmultipart/form-data
. Затем передайте их все контроллеру, если запрос соответствует требованиям.
Создайте контроллер
После того, как мы обработали маршруты, нам нужно создать контроллер для обработки процесса распознавания изображений. Сначала создайте папку с именем controllers
в корне проекта, затем создайте файл с именем PredictController.js
. После этого скопируйте в него весь этот блок.
Это объяснение из приведенного выше кода:
- Сначала импортируем все пакеты (как всегда).
- Мы просто ставим весь процесс и экспортируем их все сразу.
- В экспортируемой функции есть две основные функции:
loadModel()
иimage()
, которые будут объяснены ниже.
ФункцияloadModel()
выполняет следующие действия:
- Загрузка SavedModel с помощью
await tf.node.loadSavedModel()
- Сделайте прогноз и получите результат с помощью
await model.predict().data()
- Превратите результат прогноза в массив, а затем отправьте его в качестве ответа.
Функция image()
выполняет следующие шаги:
- Прочитайте загруженное изображение, которое будет предсказано.
- Преобразуйте изображение в тензоры, чтобы модель могла предсказать его.
- Поскольку модель была построена для чтения изображения с формой
(None, 150, 150, 3)
, нам также нужно изменить размер этого тензора на эту форму наresizeNearestNeighbor()
, чтобы изменить размер изображения до 150 x 150, и наexpandDims()
, чтобы добавить одно измерение. Поскольку изображение уже было в RGB, нам не нужно беспокоиться о3
в форме. - После этого нормализуем тензоры изображения, разделив их на 255.
- Затем мы вызываем
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.