Слои 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()
метод.