Layers 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 '@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
выборка . Обратите внимание, что async
— это конструкция, которой нет в Python. В то время как метод fit()
в Keras возвращает объект History, аналог метода fit()
в JavaScript возвращает Promise of History, который можно ожидать (как в приведенном выше примере) или использовать с методом then().
Нет NumPy для TensorFlow.js
Пользователи Python Keras часто используют NumPy для выполнения основных операций с числами и массивами, таких как создание двумерных тензоров в приведенном выше примере.
# 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) ключевое слово «новый» сделает код более раздутым и 2) «новый» конструктор считается «плохой частью» JavaScript: потенциальной ловушкой, поскольку утверждается в JavaScript: The Good Parts . Для создания моделей и слоев в TensorFlow.js вы вызываете фабричные методы с именами в нижнем регистре CamelCase, например:
// JavaScript:
const model = tf.sequential();
const layer = tf.layers.batchNormalization({axis: 1});
Значения строк опций — lowerCamelCase, а не змея_case.
В JavaScript чаще используется верблюжий регистр для имен символов (например, см. Руководство по стилю Google JavaScript ), по сравнению с Python, где распространен змеиный регистр (например, в Keras). Таким образом, мы решили использовать нижний CamelCase для строковых значений параметров, включая следующие:
- Формат данных, например,
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 метод вызова может работать только с (Python) объектами tf.Tensor
(при условии, что бэкэнд TensorFlow), которые являются символическими и не содержат фактических числовых значений. Это то, что показано в примере из предыдущего раздела. Однако в TensorFlow.js метод слоев apply() может работать как в символьном, так и в императивном режимах. Если apply()
вызывается с помощью SymbolicTensor (близкая аналогия tf.Tensor), возвращаемое значение будет SymbolicTensor. Обычно это происходит во время построения модели. Но если 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 модель можно обучить с помощью объекта набора данных . Метод fit()
модели напрямую принимает такой объект. Модель TensorFlow.js также можно обучить с помощью JavaScript-эквивалента объектов набора данных (см . документацию по API tf.data в TensorFlow.js ). Однако, в отличие от Python, обучение на основе набора данных выполняется с помощью специального метода, а именно fitDataset . Метод fit() предназначен только для обучения модели на основе тензора.
Управление памятью объектов Layer и Model
TensorFlow.js работает на WebGL в браузере, где веса объектов Layer и Model поддерживаются текстурами WebGL. Однако WebGL не имеет встроенной поддержки сборки мусора. Объекты «Слой» и «Модель» внутренне управляют тензорной памятью пользователя во время вызовов логического вывода и обучения. Но они также позволяют пользователю удалять их, чтобы освободить память WebGL, которую они занимают. Это полезно в тех случаях, когда создается и выпускается множество экземпляров модели при загрузке одной страницы. Чтобы удалить объект Layer или Model, используйте метод dispose()
.