API слоев TensorFlow.js для пользователей Keras

Слои API из TensorFlow.js смоделирован Keras , и мы стремимся сделать Layers API как аналог Keras разумными с учетом различий между JavaScript и Python. Это упрощает пользователям, имеющим опыт разработки моделей Keras на Python, переход на слои TensorFlow.js в JavaScript. Например, следующий код Keras переводится в JavaScript:

# Python:
import keras
import numpy as np

# Build and compile model.
model = keras.Sequential()
model.add(keras.layers.Dense(units=1, input_shape=[1]))
model.compile(optimizer='sgd', loss='mean_squared_error')

# Generate some synthetic data for training.
xs = np.array([[1], [2], [3], [4]])
ys = np.array([[1], [3], [5], [7]])

# Train model with fit().
model.fit(xs, ys, epochs=1000)

# Run inference with predict().
print(model.predict(np.array([[5]])))
// JavaScript:
import * as tf from '@tensorlowjs/tfjs';

// Build and compile model.
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [1]}));
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});

// Generate some synthetic data for training.
const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]);
const ys = tf.tensor2d([[1], [3], [5], [7]], [4, 1]);

// Train model with fit().
await model.fit(xs, ys, {epochs: 1000});

// Run inference with predict().
model.predict(tf.tensor2d([[5]], [1, 1])).print();

Однако есть некоторые отличия, которые мы хотели бы обозначить и объяснить в этом документе. Как только вы поймете эти различия и их обоснование, переход с Python на JavaScript (или переход в обратном направлении) должен пройти относительно гладко.

Конструкторы принимают объекты JavaScript как конфигурации

Сравните следующий Python и JavaScript строку из примера выше: они оба создают Плотный слой.

# Python:
keras.layers.Dense(units=1, inputShape=[1])
// JavaScript:
tf.layers.dense({units: 1, inputShape: [1]});

Функции JavaScript не имеют эквивалента аргументов ключевого слова в функциях Python. Мы хотим , чтобы избежать реализаций вариантов конструктора как позиционные аргументы в JavaScript, который будет особенно громоздкими запомнить и использовать для конструкторов с большим количеством ключевых слов аргументов (например, LSTM ). Вот почему мы используем объекты конфигурации JavaScript. Такие объекты обеспечивают тот же уровень позиционной инвариантности и гибкости, что и аргументы ключевого слова Python.

Некоторые методы класса модели, например, Model.compile() , а также принять объект конфигурации JavaScript в качестве входных данных. Однако, имейте в виду , что Model.fit() , Model.evaluate() и Model.predict() немного отличаются. Так как они принимают метод обязательного x (признаки) и y (метки или целей) данных в качестве входов; x и y являются позиционными аргументами отдельно от последующего объекта конфигурации , которая играет роль именованных аргументов. Например:

// JavaScript:
await model.fit(xs, ys, {epochs: 1000});

Model.fit () является асинхронным

Model.fit() является основным методом , с которым пользователи выполняют модель обучения в TensorFlow.js. Этот метод часто может быть длительным, длится секунды или минуты. Таким образом, мы используем async функцию языка JavaScript, так что эта функция может быть использована таким образом , чтобы не блокировать основной поток пользовательского интерфейса при работе в браузере. Это похоже на другие потенциально долгоиграющие функции JavaScript, такие как async выборку . Обратите внимание , что async представляет собой конструкцию , которая не существует в Python. В то время как fit() метод Keras возвращает объект истории, двойник fit() метод в JavaScript возвращает Promise истории, которая может быть Await - е изд (как в примере выше) или использовать с методом , то ().

Нет NumPy для TensorFlow.js

Пользователи Python Keras часто используют NumPy для выполнения основных числовые и массив операций, таких как генерация 2D тензоров в примере выше.

# Python:
xs = np.array([[1], [2], [3], [4]])

В TensorFlow.js такие базовые числовые операции выполняются с самим пакетом. Например:

// JavaScript:
const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]);

tf.* Имена также предоставляет ряд других функций для массивов и линейной алгебры операций , таких как умножение матриц. Смотрите документацию TensorFlow.js Core , для получения дополнительной информации.

Используйте фабричные методы, а не конструкторы

Эта строка в Python (из приведенного выше примера) является вызовом конструктора:

# Python:
model = keras.Sequential()

Если перевести строго на JavaScript, эквивалентный вызов конструктора будет выглядеть следующим образом:

// JavaScript:
const model = new tf.Sequential();  // !!! DON'T DO THIS !!!

Однако мы решили не использовать «новые» конструкторы, потому что 1) ключевое слово «new» сделало бы код более раздутым и 2) конструктор «new» рассматривается как «плохая часть» JavaScript: потенциальная ловушка, поскольку утверждается , в JavaScript: хорошие части . Для создания моделей и слоев в TensorFlow.js вы вызываете фабричные методы с именами lowerCamelCase, например:

// JavaScript:
const model = tf.sequential();

const layer = tf.layers.batchNormalization({axis: 1});

Строковые значения параметра - lowerCamelCase, а не snake_case

В JavaScript, это более распространено использование ГорбатыйРегистр для символьных имен (например, см Google JavaScript Руководства по стилю ), по сравнению с Python, где змея случае является общим (например, в Keras). Таким образом, мы решили использовать lowerCamelCase для строковых значений параметров, включая следующие:

  • DataFormat, например, channelsFirst вместо channels_first
  • Initializer, например, glorotNormal вместо glorot_normal
  • Утрата и метрики, например, meanSquaredError вместо mean_squared_error , categoricalCrossentropy вместо categorical_crossentropy .

Например, как в примере выше:

// JavaScript:
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});

Что касается сериализации и десериализации моделей, будьте уверены. Внутренний механизм TensorFlow.js обеспечивает правильную обработку случаев змей в объектах JSON, например, при загрузке предварительно обученных моделей из Python Keras.

Запускайте объекты Layer с помощью apply (), а не вызывая их как функции

В Keras, объект Слой имеет __call__ метод , определенный. Следовательно, пользователь может вызвать логику уровня, вызвав объект как функцию, например,

# Python:
my_input = keras.Input(shape=[2, 4])
flatten = keras.layers.Flatten()

print(flatten(my_input).shape)

Этот синтаксический сахар Python реализован как метод apply () в TensorFlow.js:

// JavaScript:
const myInput = tf.input({shape: [2, 4]});
const flatten = tf.layers.flatten();

console.log(flatten.apply(myInput).shape);

Layer.apply () поддерживает императивную (нетерпеливую) оценку конкретных тензоров

В настоящее время в Keras, вызов метода может работать только на (Python) TensorFlow в tf.Tensor объектов ( в предположении , TensorFlow бэкенд), которые являются символическими и не держат фактические числовые значения. Это то, что показано в примере в предыдущем разделе. Однако в TensorFlow.js метод слоев apply () может работать как в символьном, так и в императивном режимах. Если apply() вызывается с SymbolicTensor (близкой аналогии tf.Tensor), возвращаемое значение будет SymbolicTensor. Обычно это происходит во время построения модели. Но если apply() вызывается с фактическим значением конкретного Tensor, он будет возвращать бетон Tensor. Например:

// JavaScript:
const flatten = tf.layers.flatten();

flatten.apply(tf.ones([2, 3, 4])).print();

Эта функция напоминает (Python) TensorFlow в Eager исполнения . Он обеспечивает большую интерактивность и возможность отладки во время разработки модели, а также открывает двери для создания динамических нейронных сетей.

Оптимизаторы тренируются. , а не оптимизаторы.

В Keras, конструктор для объектов Оптимизатор находятся под keras.optimizers.* Пространство имен. В TensorFlow.js Layers, фабричные методы оптимизаторы находятся под tf.train.* Пространство имен. Например:

# Python:
my_sgd = keras.optimizers.sgd(lr=0.2)
// JavaScript:
const mySGD = tf.train.sgd({lr: 0.2});

loadLayersModel () загружается с URL-адреса, а не из файла HDF5

В Keras, модель, как правило , сохраняется в виде файла HDF5 (.h5), который затем может быть загружен с помощью keras.models.load_model() метода. Метод принимает путь к файлу .h5. Аналогом load_model() в TensorFlow.js является tf.loadLayersModel() . Поскольку HDF5 не браузер дружественный формат файла, tf.loadLayersModel() принимает формат TensorFlow.js специфичный. tf.loadLayersModel() принимает model.json файл как входной аргумент. Модель model.json можно преобразовать из файла Keras HDF5 с помощью пакета pip tensorflowjs.

// JavaScript:
const model = await tf.loadLayersModel('https://foo.bar/model.json');

Также отметим , что tf.loadLayersModel() возвращает Promise о tf.Model .

В целом, сохранение и загрузка tf.Model с в TensorFlow.js осуществляются с помощью tf.Model.save и tf.loadLayersModel методы, соответственно. Мы разработали этот API , чтобы быть похожими на Сохранить и load_model API из Keras. Но среда браузера сильно отличается от серверной среды, в которой работают основные фреймворки глубокого обучения, такие как Keras, особенно в массиве маршрутов для сохранения и передачи данных. Следовательно, есть некоторые интересные различия между API сохранения / загрузки в TensorFlow.js и в Keras. Смотрите наш учебник по Сохранение и загрузка tf.Model для более подробной информации.

Использование fitDataset() для моделей поездов с использованием tf.data.Dataset объектов

В tf.keras Python TensorFlow, в модель может быть обучен с помощью Dataset объекта. В модели fit() метод принимает такой объект непосредственно. TensorFlow.js модель может быть обучена с эквивалентом JavaScript в Dataset объекты , а также (см документации по API tf.data в TensorFlow.js ). Однако, в отличие от Python, Dataset-обучение осуществляется через специальный метод, а именно fitDataset . Годный () метод только для тензора на основе модели обучения.

Управление памятью объектов слоя и модели

TensorFlow.js работает в браузере на WebGL, где веса объектов Layer и Model поддерживаются текстурами WebGL. Однако в WebGL нет встроенной поддержки сборки мусора. Объекты Layer и Model внутренне управляют тензорной памятью для пользователя во время его вызовов логического вывода и обучения. Но они также позволяют пользователю избавляться от них, чтобы освободить занимаемую ими память WebGL. Это полезно в случаях, когда многие экземпляры модели создаются и выпускаются при загрузке одной страницы. Для того, чтобы расположить слой или объект Model, использовать dispose() метод.