API слоев TensorFlow.js создан по образцу Keras, и мы стремимся сделать API слоев максимально похожим на Keras, насколько это разумно, учитывая различия между JavaScript и Python. Это упрощает переход на слои TensorFlow.js в JavaScript для пользователей, имеющих опыт разработки моделей Keras на Python. Например, следующий код 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 '@tensorflow/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, например 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
fetch . Обратите внимание, что async
— это конструкция, которой нет в Python. В то время как метод fit()
в Keras возвращает объект History, аналог метода fit()
в JavaScript возвращает Promise of History, который можно ожидать (как в примере выше) или использовать с методом then().
Нет 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) «новый» конструктор считается «плохой частью» JavaScript: потенциальной ловушкой, поскольку обсуждается в JavaScript: Good Parts . Чтобы создать модели и слои в TensorFlow.js, вы вызываете фабричные методы, имена которых имеют нижнее значение CamelCase, например:
// JavaScript:
const model = tf.sequential();
const layer = tf.layers.batchNormalization({axis: 1});
Значения строки параметра — LowerCamelCase, а не Snake_case.
В JavaScript для имен символов чаще используется верблюжий регистр (например, см. Руководство по стилю Google JavaScript ), по сравнению с Python, где распространен змеиный регистр (например, в Keras). Поэтому мы решили использовать lowCamelCase для строковых значений опций, включая следующие:
- Формат данных, например,
channelsFirst
вместоchannels_first
- Инициализатор, например,
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 для объекта Layer определен метод __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 метод вызова может работать только с объектами tf.Tensor
(Python) TensorFlow (при условии, что используется бэкэнд TensorFlow), которые являются символическими и не содержат фактических числовых значений. Это то, что показано в примере в предыдущем разделе. Однако в TensorFlow.js метод слоев apply() может работать как в символическом, так и в императивном режимах. Если apply()
вызывается с символическим тензором (близкая аналогия tf.Tensor), возвращаемым значением будет символический тензор. Обычно это происходит во время построения модели. Но если apply()
вызывается с фактическим конкретным значением Тензора, он вернет конкретный Тензор. Например:
// JavaScript:
const flatten = tf.layers.flatten();
flatten.apply(tf.ones([2, 3, 4])).print();
Эта функция напоминает Eager Execution (Python) TensorFlow. Это обеспечивает большую интерактивность и возможность отладки во время разработки модели, а также открывает возможности для создания динамических нейронных сетей.
Оптимизаторы находятся в стадии обучения. , а не оптимизаторы.
В Keras конструкторы объектов Optimizer находятся в пространстве имен keras.optimizers.*
. В слоях TensorFlow.js фабричные методы для оптимизаторов находятся в пространстве имен 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 так, чтобы они были похожи на 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, обучение на основе набора данных осуществляется с помощью специального метода, а именно fitDataset . Метод fit() предназначен только для обучения модели на основе тензоров.
Управление памятью объектов слоев и моделей
TensorFlow.js работает на WebGL в браузере, где веса объектов Layer и Model поддерживаются текстурами WebGL. Однако в WebGL нет встроенной поддержки сборки мусора. Объекты Layer и Model внутренне управляют тензорной памятью пользователя во время его логических выводов и вызовов обучения. Но они также позволяют пользователю избавиться от них, чтобы освободить занимаемую ими память WebGL. Это полезно в тех случаях, когда за одну загрузку страницы создается и выпускается множество экземпляров модели. Чтобы удалить объект Layer или Model, используйте метод dispose()
.