Платформа и среда

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

В браузере TensorFlow.js поддерживает как мобильные, так и настольные устройства. Каждое устройство имеет определенный набор ограничений, таких как доступные API-интерфейсы WebGL, которые автоматически определяются и настраиваются для вас.

В Node.js TensorFlow.js поддерживает прямую привязку к TensorFlow API или работу с более медленными ванильными реализациями ЦП.

Окружающая среда

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

Бэкенды

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

Чтобы узнать, какой бэкенд вы используете:

console.log(tf.getBackend());

Если вы хотите вручную изменить бэкэнд:

tf.setBackend('cpu');
console.log(tf.getBackend());

Серверная часть WebGL

Серверная часть WebGL, 'webgl', в настоящее время является самой мощной серверной частью для браузера. Этот бэкэнд до 100 раз быстрее, чем бэкэнд ванильного процессора. Тензоры хранятся в виде текстур WebGL, а математические операции реализуются в шейдерах WebGL. Вот несколько полезных вещей, которые нужно знать при использовании этого бэкенда: \

Избегайте блокировки потока пользовательского интерфейса

Когда вызывается операция, например tf.matMul(a, b), результирующий tf.Tensor возвращается синхронно, однако вычисление матричного умножения может быть еще не готово. Это означает, что возвращаемый tf.Tensor является просто дескриптором вычисления. При вызове x.data() или x.array() , значения будут решать , когда вычисление фактически завершено. Это делает его важным использовать асинхронный x.data() и x.array() методы над их аналогами синхронных x.dataSync() и x.arraySync() , чтобы избежать блокировки потока пользовательского интерфейса в то время вычисления завершается.

Управление памятью

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

Для того, чтобы уничтожить память о tf.Tensor , вы можете использовать dispose() метод:

const a = tf.tensor([[1, 2], [3, 4]]);
a.dispose();

Очень часто в приложении несколько операций объединяются в цепочку. Сохранение ссылок на все промежуточные переменные для их удаления может снизить читаемость кода. Чтобы решить эту проблему, TensorFlow.js обеспечивает tf.tidy() метод , который очищает все tf.Tensor с, не возвращается функцией после его запуска, подобно тому, как локальные переменные очищены , когда функция выполняется:

const a = tf.tensor([[1, 2], [3, 4]]);
const y = tf.tidy(() => {
  const result = a.square().log().neg();
  return result;
});
Точность

На мобильных устройствах WebGL может поддерживать только 16-битные текстуры с плавающей запятой. Однако большинство моделей машинного обучения обучаются с использованием 32-битных весов с плавающей запятой и активаций. Это может вызвать проблемы точности при переносе модели для мобильного устройства , как 16 бита с плавающими числами могут представлять только число в диапазоне [0.000000059605, 65504] . Это означает, что вы должны быть осторожны, чтобы веса и активации в вашей модели не превышали этот диапазон. Для того, чтобы проверить , является ли устройство опоры 32 - битные текстуры, проверить значение tf.ENV.getBool('WEBGL_RENDER_FLOAT32_CAPABLE') , если это неверно , то устройство поддерживает только 16 - битные текстуры с плавающей точкой. Вы можете использовать tf.ENV.getBool('WEBGL_RENDER_FLOAT32_ENABLED') , чтобы проверить , если TensorFlow.js в настоящее время использует 32 - битные текстуры.

Компиляция шейдеров и загрузка текстур

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

TensorFlow.js также хранит данные tf.Tensor в виде WebGLTextures. Когда tf.Tensor создан, мы не сразу загружать данные на GPU, а мы сохраняем данные о процессоре , пока tf.Tensor не используется в работе. Если tf.Tensor используется во второй раз, данные уже на GPU , так что не стоимость загрузки. В типичной модели машинного обучения это означает, что веса загружаются во время первого прогноза через модель, и второй проход через модель будет намного быстрее.

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

Например:

const model = await tf.loadLayersModel(modelUrl);

// Warmup the model before using real data.
const warmupResult = model.predict(tf.zeros(inputShape));
warmupResult.dataSync();
warmupResult.dispose();

// The second predict() will be much faster
const result = model.predict(userData);

Серверная часть Node.js TensorFlow

В бэкэнде TensorFlow Node.js, «узле», API-интерфейс TensorFlow C используется для ускорения операций. При этом будет использоваться доступное аппаратное ускорение машины, например CUDA, если оно доступно.

В этом интерфейсе, так же , как WebGL бэкэндом, операции возвращают tf.Tensor S синхронно. Однако, в отличие от серверной части WebGL, операция завершается до того, как вы вернете тензор. Это означает , что вызов tf.matMul(a, b) будет блокировать поток пользовательского интерфейса.

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

Дополнительные сведения о Node.js см. в этом руководстве.

Серверная часть WASM

TensorFlow.js обеспечивает бэкенд WebAssembly ( wasm ), что ускорение предложения процессора и может быть использован в качестве альтернативы ванили JavaScript CPU ( cpu ) и WebGL ускорен ( webgl ) бэкендов. Чтобы использовать его:

// Set the backend to WASM and wait for the module to be ready.
tf.setBackend('wasm');
tf.ready().then(() => {...});

Если сервер обслуживает .wasm файл на другой путь или другое имя, используйте setWasmPath перед тем как инициализировать бэкенд. Смотрите «Использование Упаковщики» раздел в README для получения дополнительной информации:

import {setWasmPath} from '@tensorflow/tfjs-backend-wasm';
setWasmPath(yourCustomPath);
tf.setBackend('wasm');
tf.ready().then(() => {...});
Почему ВАСМ?

WASM был введен в 2015 году в качестве нового веб-двоичном формате, обеспечивая программы , написанные на JavaScript, C, C ++ и т.д. компиляции цели для работы в Сети. WASM был поддерживается с помощью Chrome, Safari, Firefox и Краю с 2017 года, и поддерживается 90% устройств по всему миру.

Представление

WASM бэкенд использует библиотеку XNNPACK для оптимизации реализации нейронных сетей операторов.

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

Против WebGL: WebGL быстрее , чем WASM для большинства моделей, но и для маленьких моделей WASM может опережать WebGL из - за постоянные накладные расходы выполнения WebGL шейдеров. В разделе «Когда следует использовать WASM» ниже обсуждаются эвристики для принятия этого решения.

Портативность и стабильность

WASM имеет портативную 32-битную арифметику с плавающей запятой, обеспечивающую точность четности на всех устройствах. WebGL, с другой стороны, зависит от аппаратного обеспечения, и разные устройства могут иметь разную точность (например, возврат к 16-битным числам с плавающей запятой на устройствах iOS).

Как и WebGL, WASM официально поддерживается всеми основными браузерами. В отличие от WebGL, WASM может работать в Node.js и использоваться на стороне сервера без необходимости компилировать собственные библиотеки.

Когда мне следует использовать WASM?

Размер модели и требования к вычислительным ресурсам

В общем, WASM выбор хорош , когда модели меньше или вы заботитесь о нижнем конечных устройствах , которые не имеют поддержку WebGL ( OES_texture_float расширение) или имеют менее мощные графические процессоры. На диаграмме ниже показано , умозаключение раз (по TensorFlow.js 1.5.2) в Chrome на 2018 год MacBook Pro за 5 наших официально поддерживаемых моделей через WebGL, WASM и бэкэндов CPU:

Меньшие модели

Модель WebGL ВАСМ Процессор объем памяти
BlazeFace 22,5 мс 15,6 мс 315,2 мс 0,4 МБ
FaceMesh 19,3 мс 19,2 мс 335 мс 2,8 МБ

Большие модели

Модель WebGL ВАСМ Процессор объем памяти
Поснет 42,5 мс 173,9 мс 1514,7 мс 4,5 МБ
БодиПикс 77 мс 188,4 мс 2683 мс 4,6 МБ
Мобильная сеть v2 37 мс 94 мс 923,6 мс 13 МБ

Приведенная выше таблица показывает , что WASM является в 10-30 раз быстрее , чем обычный бэкэндом JS CPU через модели, и конкурировать с WebGL для небольших моделей , таких как BlazeFace , что легкий (400KB), но имеет приличное количество OPS (~ 140). Учитывая, что программы WebGL имеют фиксированные накладные расходы на выполнение операции, это объясняет, почему такие модели, как BlazeFace, работают быстрее на WASM.

Эти результаты будут различаться в зависимости от вашего устройства. Лучший способ определить, подходит ли WASM для вашего приложения, — это протестировать его на разных серверах.

Вывод против обучения

Для решения основного потребительного случая для развертывания предварительно подготовленные моделей, разработка WASM бэкенда будет уделять первостепенное внимание умозаключения через обучение поддержки. Обнаружил список уточненного поддерживаемых опов WASM и дайте нам знать , если ваша модель имеет неподдерживаемый цит. Для моделей обучения мы рекомендуем использовать серверную часть Node (TensorFlow C++) или серверную часть WebGL.

Серверная часть процессора

Серверная часть ЦП, «cpu», является наименее производительной, однако самой простой. Все операции реализованы на ванильном JavaScript, что делает их менее распараллеливаемыми. Они также блокируют поток пользовательского интерфейса.

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

Флаги

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

  • tf.enableProdMode(): включает режим производства, что приведет к удалению модели проверки, NaN проверки и другие проверки корректности в пользу производительности.
  • tf.enableDebugMode() : включает режим отладки, который будет регистрировать на консоль каждую операцию, которая выполняется, а также информацию о производительности во время выполнения , как объем памяти и общее время выполнения ядра. Обратите внимание, что это сильно замедлит ваше приложение, не используйте это в продакшене.