Машинное обучение в Node.js с TensorFlow.js

TensorFlow

TensorFlow.js — это новая версия популярной библиотеки с открытым исходным кодом, которая обеспечивает глубокое обучение JavaScript. Теперь разработчики могут использовать высокоуровневые API-интерфейсы библиотек для определения, обучения и запуска моделей машинного обучения.

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

Начиная с интерфейсной библиотеки для веб-браузеров, последние обновления добавили экспериментальную поддержку Node.js. Это позволяет использовать TensorFlow.js в серверных приложениях JavaScript без необходимости использования Python.

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

Распознавание изображений через Node.js с использованием TensorFlow.js

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

Но, после нескольких дней обучения день и ночь, я закончил! радость! ?

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

TensorFlow

TensorFlow— это программная библиотека с открытым исходным кодом для приложений машинного обучения.TensorFlowМожет использоваться для реализации нейронных сетей и других алгоритмов глубокого обучения.

TensorFlowк ноябрю 2015 г.Googleопубликовано, первоначальноPythonбиблиотека. Он использует вычисления на базе процессора или графического процессора для обучения и оценки моделей машинного обучения. Библиотека изначально была разработана для работы на высокопроизводительных серверах с дорогими графическими процессорами.

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

TensorFlow Lite

Tensorflow Lite— облегченная версия библиотеки для мобильных и встраиваемых устройств, выпущенная в мае 2017 года. Этот выпуск поставляется с новым набором предварительно обученных моделей глубокого обучения для задач визуального распознавания, называемыхMobileNet.MobileNetМодели предназначены для эффективной работы в средах с ограниченными ресурсами, таких как мобильные устройства.

TensorFlow.js

существуетTensorflow Liteпосле,TensorFlow.jsОпубликовано в марте 2018 года. Эта версия библиотеки предназначена для работы в браузере и построена наdeeplearn.jsна раннем проекте. WebGL обеспечивает доступ графического процессора к библиотеке. разработчики используютJavaScript APIОбучите, загрузите и запустите модель.

TensorFlow.jsнедавно прошелtfjs-nodeБиблиотека расширений находится вNode.jsзапускать на.

Расширение Node.js — этоAlphaверсия, все еще в активной разработке

Импортируйте существующую модель в Tensorflow.js

можно использоватьTensorFlow.jsБиблиотека реализует существующуюTensorFlowиKerasМодель. Перед выполнением модели необходимо преобразовать в новый формат с помощью этого инструмента. Github предоставляет предварительно обученные и трансляционные модели для классификации изображений, определения позы и k-ближайших соседей.

Использование tensorflow.js в nodejs

Установите библиотеку tensorflow.

TensorFlow.jsсуществуетNPMУстановить из библиотеки.

@tensorflow/tfjs - 核心TensorFlow.js包

@tensorflow/tfjs-node - TensorFlow.js的Node.js 扩展

@tensorflow/tfjs-node-gpu - TensorFlow.js 的GPU支持的nodejs扩展

npm install @tensorflow/tfjs @tensorflow/tfjs-node
// or...
npm install @tensorflow/tfjs @tensorflow/tfjs-node-gpu

Оба расширения Node.js используют собственные зависимости, которые будут скомпилированы по мере необходимости.

Загрузите библиотеку tensorflow

Пользователям доступен JavaScript API TensorFlow. Модули расширения, поддерживаемые Node.js, не предоставляют дополнительных API.

const tf = require('@tensorflow/tfjs')
// Load the binding (CPU computation)
require('@tensorflow/tfjs-node')
// Or load the binding (GPU computation)
require('@tensorflow/tfjs-node-gpu')

Загрузите модель тензорного потока

TensorFlow.jsпредоставилNPMбиблиотека (tfjs-models), чтобы легко загружать предварительно обученные и преобразованные модели для классификации изображений, определения позы и k-ближайших соседей.

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

В файле README проекта для загрузки модели используется следующий пример кода.

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

// Load the model.
const model = await mobilenet.load();

Первая проблема, с которой я столкнулся, заключается в том, что это не работает на Node.js.

Error: browserHTTPRequest is not supported outside the web browser.

Посмотреть исходный код,mobilenetБиблиотеки – это основаtf.ModelОбертка класса. перечислитьload(), он автоматически загрузит правильный файл модели с внешнего HTTP-адреса и создаст экземпляр.TensorFlowМодель.

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

После прочтения исходного кода библиотеки мне удалось создать обходной путь...

Загрузите модель из файловой системы

Если создать вручнуюMobileNetкласс, вам не нужно вызывать модульloadвместо этого вы можете переопределить автоматически сгенерированную переменную пути, содержащую HTTP-адрес модели, с путем в локальной файловой системе. Как только это будет сделано, вызов метода load для экземпляра класса вызовет класс загрузчика файловой системы вместо того, чтобы пытаться использовать метод на основе браузера.HTTPЗагрузчик.

const path = "mobilenet/model.json"
const mn = new mobilenet.MobileNet(1, 1);
mn.path = `file://${path}`
await mn.load()

Отлично, это работает!

Но откуда берутся файлы модели?

Модель мобильной сети

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

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

https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v${version}_${alpha}_${size}/

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

Согласно исходному коду, используйтеtensorflow-models / mobilenetБиблиотеки могут быть загружены толькоMobileNet v1Модель.

Код извлечения HTTP загружается из этого места.model.jsonфайл, а затем рекурсивно получить все осколки веса модели, на которые ссылаются. Формат этих файловgroupX-shard1of1.

Скачать модель вручную

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

Я хочу использовать модуль MobileNet V1 с альфа-значением 1,0 и размером изображения 224 пикселя. Это дает мне следующий URL-адрес для файла конфигурации модели.

https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/model.json

После загрузки этого файла локально я могу использоватьjqинструмент для разбора всех имен файлов.

$ cat model.json | jq -r ".weightsManifest[].paths[0]"
group1-shard1of1
group2-shard1of1
group3-shard1of1
...

использоватьsedинструменты, я могу добавить эти именаHTTP URLПрефикс, URL генерируется для каждого файла.

$ cat model.json | jq -r ".weightsManifest[].paths[0]" | sed 's/^/https:\/\/storage.googleapis.com\/tfjs-models\/tfjs\/mobilenet_v1_1.0_224\//'
https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/group1-shard1of1
https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/group2-shard1of1
https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/group3-shard1of1
...

Затем используйтеparallelиcurlкоманда для загрузки всех этих файлов в локальный каталог.

cat model.json | jq -r ".weightsManifest[].paths[0]" | sed 's/^/https:\/\/storage.googleapis.com\/tfjs-models\/tfjs\/mobilenet_v1_1.0_224\//' |  parallel curl -O

Классификация изображенийTensorFlow.jsЭтот пример кода предназначен для демонстрации возвращаемой классификации изображений.

const img = document.getElementById('img');

// Classify the image.
const predictions = await model.classify(img)   

Не работает с Node.js из-за отсутствия DOM.

Метод classify принимает ряд элементов DOM (холст, видео, изображение) и автоматически извлекает байты изображения из этих элементов и преобразует их в класс tf.Tensor3D, который используется в качестве входных данных для модели. В качестве альтернативы вход tf.Tensor3D можно передать напрямую.

Я обнаружил, что вместо того, чтобы пытаться использовать внешний пакет для имитацииNode.jsсерединаDOMэлементы, лучше построить вручнуюtf.Tensor3D.

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

const values = new Int32Array(image.height * image.width * numChannels);
// fill pixels with pixel channel bytes from image
const outShape = [image.height, image.width, numChannels];
const input = tf.tensor3d(values, outShape, 'int32'); 

pixelимеет тип(Int32Array)2D-массив, содержащий упорядоченный список значений канала для каждого пикселя.numChannels— количество значений канала на пиксель.

Создайте входное значение для JPEG

jpeg-jsбиблиотекаNode.jsчистыйJavaScript JPEGКодер и декодер. С помощью этой библиотеки можно извлечьRGBценность.

const pixel = jpeg.decode(buffer,true);

Это вернет четырехканальное значение (RGBA) для каждого пикселя (ширина * высота).Uint8Array.MobileNetМодель использует только три цветовых канала (RGB) для классификации, игнорируяalphaряд. Этот код преобразует четырехканальный массив в правильную трехканальную версию.

const numChannels = 3;
const numPixels = image.width * image.height;
const values = new Int32Array(numPixels * numChannels);

for (let i = 0; i < numPixels; i++) {
  for (let channel = 0; channel < numChannels; ++channel) {
    values[i * numChannels + channel] = pixels[i * 4 + channel];
  }
}

Требования к входным данным модели MobileNet

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

Перед классификацией входные значения для изображений разного размера необходимо изменить. Кроме того, значения пикселей из декодера JPEG находятся в диапазоне 0-255, а не от -1 до 1. Эти значения также необходимо преобразовать перед классификацией.

TensorFlow.jsЕсть библиотечные методы для упрощения этого процесса, к счастью,tfjs-models / mobilenetБиблиотеки могут справиться с этим автоматически! ?

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

предсказывать

TensorflowсерединаMobileNetМодель обучена распознаватьImageNetОбъекты из 1000 лучших категорий в наборе данных. Модель выводит вероятность того, что каждый из этих объектов находится на классифицированном изображении.

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

tfjs-models / mobilenetбиблиотекаMobileNetМетод классификации предоставляется в классе, чтобы вернуть X лучших классов с наибольшей вероятностью из входного изображения.

const predictions = await mn_model.classify(input, 10);

predictionsпредставляет собой массив X классов и вероятностей в следующем формате.

{
  className: 'panda',
  probability: 0.9993536472320557
}

пример

учился, какNode.js上использоватьTensorFlow.jsбиблиотека иMobileNetПосле модели этот сценарий будет классифицировать изображения, переданные в качестве аргументов командной строки.

исходный код Сохраните этот файл сценария и дескриптор пакета в локальный файл.

//package.json
{
  "name": "tf-js",
  "version": "1.0.0",
  "main": "script.js",
  "license": "MIT",
  "dependencies": {
    "@tensorflow-models/mobilenet": "^0.2.2",
    "@tensorflow/tfjs": "^0.12.3",
    "@tensorflow/tfjs-node": "^0.1.9",
    "jpeg-js": "^0.3.4"
  }
}
//script.js
const tf = require('@tensorflow/tfjs')
const mobilenet = require('@tensorflow-models/mobilenet');
require('@tensorflow/tfjs-node')

const fs = require('fs');
const jpeg = require('jpeg-js');

const NUMBER_OF_CHANNELS = 3

const readImage = path => {
  const buf = fs.readFileSync(path)
  const pixels = jpeg.decode(buf, true)
  return pixels
}

const imageByteArray = (image, numChannels) => {
  const pixels = image.data
  const numPixels = image.width * image.height;
  const values = new Int32Array(numPixels * numChannels);

  for (let i = 0; i < numPixels; i++) {
    for (let channel = 0; channel < numChannels; ++channel) {
      values[i * numChannels + channel] = pixels[i * 4 + channel];
    }
  }

  return values
}

const imageToInput = (image, numChannels) => {
  const values = imageByteArray(image, numChannels)
  const outShape = [image.height, image.width, numChannels];
  const input = tf.tensor3d(values, outShape, 'int32');

  return input
}

const loadModel = async path => {
  const mn = new mobilenet.MobileNet(1, 1);
   mn.path = `file://${path}`
  await mn.load()
  return mn
}

const classify = async (model, path) => {
  const image = readImage(path)
  const input = imageToInput(image, NUMBER_OF_CHANNELS)

  const  mn_model = await loadModel(model)
  const predictions = await mn_model.classify(input)

  console.log('classification results:', predictions)
}

if (process.argv.length !== 4) throw new Error('incorrect arguments: node script.js <MODEL> <IMAGE_FILE>')

classify(process.argv[2], process.argv[3])

контрольная работа

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

  • Установите зависимости проекта с помощью NPM

npm install

  • Загрузите образцы файлов JPEG для классификацииwget http://bit.ly/2JYSal9 -O panda.jpg

  • Запустите скрипт с файлом модели и введите изображение в качестве параметра.node script.js mobilenet/model.json panda.jpgЕсли все в порядке, следующий вывод должен быть выведен на консоль.
classification results: [ {
    className: 'giant panda, panda, panda bear, coon bear',
    probability: 0.9993536472320557
} ]

Картинка правильно классифицируется как содержащая панду с вероятностью 99,93%! ???

в заключении

TensorFlow.jsзаJavaScriptРазработчики привносят мощь глубокого обучения. существуетTensorFlow.jsИспользование предварительно обученных моделей в библиотеке позволяет легко масштабировать сложные задачи машинного обучения с минимальными усилиями и кодом.JavaScriptприменение.

TensorFlow.jsВыпущена как библиотека для браузера, теперь она доступна по адресуNode.js, хотя не все инструменты и утилиты поддерживают новую среду выполнения. После нескольких дней исследований я могу использовать библиотеку сMobileNetМодели используются вместе для визуального распознавания изображений в локальных файлах.

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