[Перевод] Бессерверное машинное обучение с TensorFlow.js

TensorFlow Программа перевода самородков Docker JavaScript

существуетв предыдущих блогах, я объяснил, как использоватьTensorFlow.jsЗапустите его на Node.jsВизуальное распознавание в местных изображениях. TensorFlow.js — это JavaScript-версия библиотеки машинного обучения с открытым исходным кодом от Google.

Как только мой локальный скрипт Node.js заработал, моей следующей мыслью было преобразовать его в бессерверную функцию. я буду вIBM Cloud Functions(Apache OpenWhisk), чтобы запустить эту функцию и превратить скрипт в собственный микросервис для визуального распознавания.

Без сервера с TensorFlow.js

Кажется легким, правда? Это просто библиотека JavaScript? Итак, распакуйте его, и мы перейдем к делу...Ага?;

Преобразование и запуск сценария классификации изображений в среде без серверной архитектуры сопряжены со следующими проблемами:

  • Библиотеку TensorFlow.js необходимо загружать во время выполнения.
  • Собственные привязки файлов библиотеки должны быть скомпилированы в соответствии с архитектурой платформы.
  • Файлы модели должны быть загружены из файловой системы.

Некоторые из этих вопросов будут более сложными, чем другие! Давайте объясним, как использовать Apache OpenWhiskDocker supportПрежде чем решать каждую проблему, давайте рассмотрим детали каждой проблемы.

вызов

Библиотека TensorFlow.js

Библиотека TensorFlow.js не входит в состав Apache OpenWhisk.Библиотеки для среды выполнения Node.js

Внешние библиотеки можно развернуть, развернув приложение из zip-файла.импортировать в рантаймВремя. zip-файл содержит пользовательские папкиnode_modulesизвлекается в среду выполнения. Максимальный размер Zip-файлаОграничено до 48 МБ.

размер библиотеки

Для использования библиотеки TensorFlow.js требуется запустить командуnpm installЗдесь возникает первая проблема... т.е. сгенерированныйnode_modulesРазмер папки 175MB. ?

Просмотрите содержимое этой папки,tfjs-nodeМодуль компилирует 135Mлокальная общая библиотека(libtensorflow.so). Это означает, что в соответствии с этим волшебным правилом ограничения в 48 МБ не так много JavaScript, который можно минимизировать до предела, необходимого для получения этих внешних зависимостей. ?

локальные зависимости

локальная общая библиотекаlibtensorflow.soДля компиляции должна использоваться среда выполнения платформы. работать локальноnpm installМашинные зависимости для хост-платформы компилируются автоматически. Локальные среды могут использовать разные архитектуры ЦП (Mac и Linux) или связываться с общими библиотеками, недоступными в бессерверной среде выполнения.

Файл модели MobileNet

Файл модели TensorFlowТребуется загрузка из файловой системы в Node.js. Бессерверная среда выполнения предоставляет временную файловую систему в среде выполнения. Соответствующие файлы в ZIP-файле развертывания автоматически распаковываются в эту среду перед вызовом. Внешний доступ к этой файловой системе отсутствует за пределами времени существования необслуживаемой функции.

Размер файла модели MobileNet составляет 16 МБ. Если эти файлы включены в пакет развертывания, остальная часть исходного кода приложения останется размером 32 МБ. Хотя файлы модели достаточно малы, чтобы их можно было включить в zip-файл, как насчет библиотеки TensorFlow.js? Это конец статьи? Не так быстро….

Поддержка Apache OpenWhisk пользовательских сред выполнения обеспечивает простое решение всех этих проблем!

пользовательская среда выполнения

Apache OpenWhisk использует контейнеры Docker в качестве среды выполнения для бессерверных функций (операций). Все образы среды выполнения платформы доступны вВыпуск Docker Hub, что позволяет разработчикам запускать эти среды локально.

Разработчики также могут создавать действия, когдаПользовательский образ запуска. Эти образы должны быть общедоступны на Docker Hub. Пользовательские среды выполнения должны предоставлять платформу для вызоватот же HTTP-API.

Используйте образ среды выполнения платформы какродительское изображениеМожет упростить создание пользовательских сред выполнения. Пользователи могут запускать команды во время сборки Docker для установки дополнительных библиотек и других зависимостей. Родительский образ уже содержит исходные файлы со службой Http API для обработки запросов платформы.

Среда выполнения TensorFlow.js

Ниже приведен файл сборки Docker для среды выполнения действий Node.js, включая другие зависимости TensorFlow.js.

FROM openwhisk/action-nodejs-v8:latest

RUN npm install @tensorflow/tfjs @tensorflow-models/mobilenet @tensorflow/tfjs-node jpeg-js

COPY mobilenet mobilenet

openwhisk/action-nodejs-v8:latest— это изображение, опубликованное OpenWhisk с установленной средой выполнения Node.js.

используется в процессе сборкиnpm installУстановите библиотеку TensorFlow и другие зависимости. Установите библиотеку в процессе сборки@tensorflow/tfjs-nodeЛокальные зависимости могут быть автоматически скомпилированы для соответствующей платформы.

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

Хотите пропустить следующий шаг? использовать это изображениеjamesthomas/action-nodejs-v8:tfjsа не создавать его самостоятельно.

построить среду выполнения

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

  • Загрузите версию модели MobileNet и поместите все файлы вmobilenetв каталоге.
  • Скопируйте файл сборки Docker локально и назовите егоDockerfile.
  • запустить докерbuild commandСоздайте локальный образ.
docker build -t tfjs .
docker tag tfjs <USERNAME>/action-nodejs-v8:tfjs

Замените своим именем пользователя Docker Hub.<USERNAME>

docker push <USERNAME>/action-nodejs-v8:tfjs

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

образец кода

Этот код реализует классификацию изображений как операцию OpenWhisk. Использование параметра события наimageСвойство предоставляет файл изображения в виде строки в кодировке Base64. Результаты классификации как в ответеresultsимущество возвращается.

const tf = require('@tensorflow/tfjs')
const mobilenet = require('@tensorflow-models/mobilenet');
require('@tensorflow/tfjs-node')

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

const NUMBER_OF_CHANNELS = 3
const MODEL_PATH = 'mobilenet/model.json'

let mn_model

const memoryUsage = () => {
  let used = process.memoryUsage();
  const values = []
  for (let key in used) {
    values.push(`${key}=${Math.round(used[key] / 1024 / 1024 * 100) / 100} MB`);
  }

  return `memory used: ${values.join(', ')}`
}

const logTimeAndMemory = label => {
  console.timeEnd(label)
  console.log(memoryUsage())
}

const decodeImage = source => {
  console.time('decodeImage');
  const buf = Buffer.from(source, 'base64')
  const pixels = jpeg.decode(buf, true);
  logTimeAndMemory('decodeImage')
  return pixels
}

const imageByteArray = (image, numChannels) => {
  console.time('imageByteArray');
  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];
    }
  }

  logTimeAndMemory('imageByteArray')
  return values
}

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

  logTimeAndMemory('imageToInput')
  return input
}

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

async function main (params) {
  console.time('main');
  console.log('prediction function called.')
  console.log(memoryUsage())

  console.log('loading image and model...')

  const image = decodeImage(params.image)
  const input = imageToInput(image, NUMBER_OF_CHANNELS)

  if (!mn_model) {
    mn_model = await loadModel(MODEL_PATH)
  }

  console.time('mn_model.classify');
  const predictions = await mn_model.classify(input);
  logTimeAndMemory('mn_model.classify')

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

  // free memory from TF-internal libraries from input image
  input.dispose()
  logTimeAndMemory('main')

  return { results: predictions }
}

Загруженные модели из кеша

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

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

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

Модели кэширования могут сократить время (и, следовательно, затраты) на классификацию горячих вызовов.

утечка памяти

Скрипты Node.js можно запускать из записи в блоге IBM Cloud Functions с минимальными изменениями. К сожалению, тесты производительности показывают утечку памяти в функции-обработчике. ?

Узнайте больше о Node.jsКак работает TensorFlow.jsИнформация, проливающая свет на проблему...

Расширение Node.js для TensorFlow.js использует собственные библиотеки C++ для вычисления тензоров на ядрах CPU или GPU. Память, выделенная для объектов Tensor в собственной библиотеке, резервируется до тех пор, пока приложение явно не освободит ее или процесс не завершится. TensorFlow.js обеспечивает отдельные объектыdisposeметод освобождения выделенной памяти. есть еще одинtf.tidyметод для автоматической очистки всех выделенных объектов в кадре.

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

Анализ и производительность

Исполняющий код записывает использование памяти и потребление времени на разных этапах обработки классификации.

записыватьиспользование памятиМожет позволить мне изменить максимальный объем памяти, выделенный для функции, для лучшей производительности и стоимости. Node.js предоставляетAPI стандартной библиотекидля получения информации об использовании памяти текущим процессом. Регистрация этих значений позволяет мне исследовать использование памяти на разных этапах.

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

пример

развернуть код

  • использоватьIBM Cloud CLIВыполните следующую команду, чтобы создать действие.
ibmcloud fn action create classify --docker <IMAGE_NAME> index.js

Замените общедоступным идентификатором образа Docker Hub пользовательской среды выполнения.<IMAGE_NAME>. Если вы его не строили, используйтеjamesthomas/action-nodejs-v8:tfjs.

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

wget http://bit.ly/2JYSal9 -O panda.jpg
  • Используйте изображение в кодировке Base64 в качестве входного параметра вызывающего метода.
ibmcloud fn action invoke classify -r -p image $(base64 panda.jpg)
  • Возвращенное сообщение JSON содержит вероятности классификации. ???
{
  "results":  [{
    className: 'giant panda, panda, panda bear, coon bear',
    probability: 0.9993536472320557
  }]
}

подробности активации

  • Получите последний активированный вывод журнала, чтобы отобразить данные о производительности.
ibmcloud fn activation logs --last

Сведения о профилировании и использовании памяти записываются в стандартный вывод.

prediction function called.
memory used: rss=150.46 MB, heapTotal=32.83 MB, heapUsed=20.29 MB, external=67.6 MB
loading image and model...
decodeImage: 74.233ms
memory used: rss=141.8 MB, heapTotal=24.33 MB, heapUsed=19.05 MB, external=40.63 MB
imageByteArray: 5.676ms
memory used: rss=141.8 MB, heapTotal=24.33 MB, heapUsed=19.05 MB, external=45.51 MB
imageToInput: 5.952ms
memory used: rss=141.8 MB, heapTotal=24.33 MB, heapUsed=19.06 MB, external=45.51 MB
mn_model.classify: 274.805ms
memory used: rss=149.83 MB, heapTotal=24.33 MB, heapUsed=20.57 MB, external=45.51 MB
classification results: [...]
main: 356.639ms
memory used: rss=144.37 MB, heapTotal=24.33 MB, heapUsed=20.58 MB, external=45.51 MB

main- общее время, затраченное на обработку программы.mn_model.classifyзанимает много времени для классификации изображений. Запрос на холодный запуск напечатал дополнительное сообщение журнала со временем загрузки модели,loadModel:394.547ms.

результаты работы

Вызывается для холодной активации и горячей активации (с использованием 256 МБ памяти)classifyДействие 1000 раз приводит к следующим результатам.

термическая активация

Результаты работы при нагревании

В среде с горячим стартом среднее время обработки классификации составляет316 мс. Глядя на данные, отнимающие много времени, можно сказать, что преобразование JPEG, закодированного в Base64, во входной тензор занимает около 100 мс. Запуск модели для задачи классификации занимал 200-250 мс.

холодная активация

Результаты производительности холодной активации

Большое среднее время обработки сортировки при использовании холодной среды1260 мс. Эти запросы ограничиваются инициализацией новых контейнеров среды выполнения и загрузкой моделей из файловой системы. Обе задачи занимают около 400 мс.

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

стоимость классификации

IBM Cloud Functions обеспечивает ежемесячный трафик 400 000 ГБ/с.Уровень бесплатного пользования. Дополнительная плата за вызовы в секунду составляет 0,000017 долларов США за ГБ использования памяти. Время выполнения округляется до ближайших 100 миллисекунд.

Если все активации являются горячими активациями, пользователи могут использовать 256 МБ дискового пространства иВыполняет более 4 000 000 классификаций в месяц. После выхода за пределы диапазона бесплатного уровня около 600 000 дополнительных звонков стоят немногим более 1 доллара.

Если все активации являются холодными активациями, пользователи могут использовать объем хранилища 256 МБ иВыполняет более 1 200 000 классификаций в месяц. После выхода за пределы бесплатного уровня примерно 180 000 дополнительных звонков стоят 1 доллар США.

в заключении

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

Получить локальный скрипт для запуска классификации изображений относительно просто, но преобразование в бессерверную функцию сопряжено с большими трудностями! Apache OpenWhisk ограничивает максимальный размер приложения до 50 МБ, а зависимости собственных библиотек намного больше этого ограничения.

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

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


Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.