Interfejs Layers API w TensorFlow.js jest wzorowany na Kerasie i staramy się, aby interfejs Layers API był jak najbardziej podobny do Keras, biorąc pod uwagę różnice między JavaScript i Python. Ułatwia to użytkownikom z doświadczeniem w tworzeniu modeli Keras w Pythonie migrację do warstw TensorFlow.js w JavaScript. Na przykład poniższy kod Keras jest tłumaczony na 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();
Jednak istnieją pewne różnice, które chcielibyśmy podkreślić i wyjaśnić w tym dokumencie. Gdy zrozumiesz te różnice i ich uzasadnienie, Twoja migracja z Pythona do JavaScript (lub migracja w odwrotnym kierunku) powinna być stosunkowo płynna.
Konstruktory przyjmują obiekty JavaScript jako konfiguracje
Porównaj następujące wiersze Pythona i JavaScriptu z powyższego przykładu: oba tworzą warstwę gęstą .
# Python:
keras.layers.Dense(units=1, inputShape=[1])
// JavaScript:
tf.layers.dense({units: 1, inputShape: [1]});
Funkcje JavaScript nie mają odpowiednika argumentów słów kluczowych w funkcjach Pythona. Chcemy uniknąć implementacji opcji konstruktorów jako argumentów pozycyjnych w JavaScript, co byłoby szczególnie kłopotliwe do zapamiętania i używania w przypadku konstruktorów z dużą liczbą argumentów słów kluczowych (np. LSTM ). Dlatego używamy obiektów konfiguracyjnych JavaScript. Takie obiekty zapewniają ten sam poziom niezmienności pozycyjnej i elastyczność, co argumenty słów kluczowych Pythona.
Niektóre metody klasy Model, np. Model.compile()
, również przyjmują jako dane wejściowe obiekt konfiguracyjny JavaScript. Należy jednak pamiętać, że Model.fit()
, Model.evaluate()
i Model.predict()
są nieco inne. Ponieważ metody te przyjmują obowiązkowe dane x
(cechy) i y
(etykiety lub cele) jako dane wejściowe; x
i y
są argumentami pozycyjnymi niezależnymi od wynikającego z tego obiektu konfiguracyjnego, który pełni rolę argumentów słów kluczowych. Na przykład:
// JavaScript:
await model.fit(xs, ys, {epochs: 1000});
Model.fit() jest asynchroniczny
Model.fit()
to podstawowa metoda, za pomocą której użytkownicy przeprowadzają szkolenie modelu w TensorFlow.js. Ta metoda często może być długotrwała, trwać sekundy lub minuty. Dlatego korzystamy z funkcji async
języka JavaScript, dzięki czemu funkcja ta może być używana w sposób, który nie blokuje głównego wątku interfejsu użytkownika podczas uruchamiania w przeglądarce. Jest to podobne do innych potencjalnie długotrwałych funkcji w JavaScript, takich jak pobieranie async
. Zauważ, że async
to konstrukcja, która nie istnieje w Pythonie. Podczas gdy metoda fit()
w Keras zwraca obiekt History, odpowiednik metody fit()
w JavaScript zwraca obietnicę historii, na którą można poczekać (jak w powyższym przykładzie) lub użyć z metodą then().
Brak NumPy dla TensorFlow.js
Użytkownicy Pythona Keras często używają NumPy do wykonywania podstawowych operacji numerycznych i tablicowych, takich jak generowanie tensorów 2D w powyższym przykładzie.
# Python:
xs = np.array([[1], [2], [3], [4]])
W TensorFlow.js tego rodzaju podstawowe operacje numeryczne są wykonywane na samym pakiecie. Na przykład:
// JavaScript:
const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]);
Przestrzeń nazw tf.*
udostępnia również szereg innych funkcji do operacji na tablicach i algebry liniowej, takich jak mnożenie macierzy. Więcej informacji można znaleźć w dokumentacji TensorFlow.js Core .
Używaj metod fabrycznych, a nie konstruktorów
Ta linia w Pythonie (z powyższego przykładu) to wywołanie konstruktora:
# Python:
model = keras.Sequential()
Po przetłumaczeniu wyłącznie na JavaScript, równoważne wywołanie konstruktora wyglądałoby tak:
// JavaScript:
const model = new tf.Sequential(); // !!! DON'T DO THIS !!!
Zdecydowaliśmy się jednak nie używać konstruktorów „new”, ponieważ 1) słowo kluczowe „new” sprawiłoby, że kod byłby bardziej rozdęty, a 2) konstruktor „new” jest uważany za „złą część” JavaScriptu: potencjalna pułapka, ponieważ jest argumentowany w JavaScript: the Good Parts . Aby tworzyć modele i warstwy w TensorFlow.js, wywołujesz metody fabryczne, które mają nazwy LowerCamelCase, na przykład:
// JavaScript:
const model = tf.sequential();
const layer = tf.layers.batchNormalization({axis: 1});
Wartości ciągu opcji to lowerCamelCase, a nie snake_case
W JavaScript częściej używa się wielkości liter wielbłąda dla nazw symboli (np. zobacz Przewodnik po stylu Google JavaScript ), w porównaniu z Pythonem, gdzie wielkość liter węży jest powszechna (np. w Keras). W związku z tym zdecydowaliśmy się użyć lowerCamelCase dla wartości łańcuchowych dla opcji, w tym:
- DataFormat, np.
channelsFirst
zamiastchannels_first
- Inicjator, np.
glorotNormal
zamiastglorot_normal
- Strata i metryki, np.
meanSquaredError
zamiastmean_squared_error
,categoricalCrossentropy
zamiastcategorical_crossentropy
.
Na przykład, jak w powyższym przykładzie:
// JavaScript:
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});
Zapewniamy, że w odniesieniu do serializacji i deserializacji modelu. Wewnętrzny mechanizm TensorFlow.js zapewnia, że przypadki węży w obiektach JSON są obsługiwane poprawnie, np. podczas ładowania wstępnie wytrenowanych modeli z Python Keras.
Uruchamiaj obiekty Layer za pomocą apply(), a nie przez wywoływanie ich jako funkcji
W Keras obiekt Layer ma zdefiniowaną metodę __call__
. Dlatego użytkownik może wywołać logikę warstwy, wywołując obiekt jako funkcję, np.
# Python:
my_input = keras.Input(shape=[2, 4])
flatten = keras.layers.Flatten()
print(flatten(my_input).shape)
Ten cukier składni Pythona jest zaimplementowany jako metoda apply() w TensorFlow.js:
// JavaScript:
const myInput = tf.input({shape: [2, 4]});
const flatten = tf.layers.flatten();
console.log(flatten.apply(myInput).shape);
Layer.apply() obsługuje imperatywną (chętną) ocenę na konkretnych tensorach
Obecnie w Keras metoda wywołania może działać tylko na obiektach tf.Tensor
(zakładając zaplecze TensorFlow) TensorFlow (Python), które są symboliczne i nie przechowują rzeczywistych wartości liczbowych. Jest to pokazane w przykładzie w poprzedniej sekcji. Jednak w TensorFlow.js metoda apply() warstw może działać zarówno w trybie symbolicznym, jak i imperatywnym. Jeśli metoda apply()
jest wywoływana z SymbolicTensor (bliska analogia tf.Tensor), wartością zwracaną będzie SymbolicTensor. Dzieje się tak zwykle podczas budowania modelu. Ale jeśli apply()
zostanie wywołana z rzeczywistą konkretną wartością Tensor, zwróci konkretny Tensor. Na przykład:
// JavaScript:
const flatten = tf.layers.flatten();
flatten.apply(tf.ones([2, 3, 4])).print();
Ta funkcja przypomina Eager Execution (Python) TensorFlow. Zapewnia większą interaktywność i możliwość debugowania podczas opracowywania modelu, a także otwiera drzwi do tworzenia dynamicznych sieci neuronowych.
Optymalizatory są w trakcie treningu. , a nie optymalizatory.
W Keras konstruktory obiektów Optimizer znajdują się w przestrzeni nazw keras.optimizers.*
. W warstwach TensorFlow.js metody fabryczne dla Optymalizatorów znajdują się w przestrzeni nazw tf.train.*
. Na przykład:
# Python:
my_sgd = keras.optimizers.sgd(lr=0.2)
// JavaScript:
const mySGD = tf.train.sgd({lr: 0.2});
loadLayersModel() ładuje się z adresu URL, a nie z pliku HDF5
W Keras modele są zwykle zapisywane jako plik HDF5 (.h5), który można później wczytać za pomocą metody keras.models.load_model()
. Metoda pobiera ścieżkę do pliku .h5. Odpowiednikiem load_model()
w TensorFlow.js jest tf.loadLayersModel()
. Ponieważ HDF5 nie jest formatem przyjaznym dla przeglądarek, tf.loadLayersModel()
przyjmuje format specyficzny dla TensorFlow.js. tf.loadLayersModel()
przyjmuje plik model.json jako argument wejściowy. Model.json można przekonwertować z pliku Keras HDF5 przy użyciu pakietu tensorflowjs pip.
// JavaScript:
const model = await tf.loadLayersModel('https://foo.bar/model.json');
Należy również zauważyć, że tf.loadLayersModel()
zwraca Promise
tf.Model
.
Ogólnie rzecz biorąc, zapisywanie i ładowanie tf.Model
s w TensorFlow.js odbywa się za pomocą odpowiednio metod tf.Model.save
i tf.loadLayersModel
. Zaprojektowaliśmy te interfejsy API, aby były podobne do API save i load_model Keras. Jednak środowisko przeglądarki różni się znacznie od środowiska zaplecza, na którym działają podstawowe platformy uczenia głębokiego, takie jak Keras, szczególnie w zakresie szeregu tras do utrwalania i przesyłania danych. W związku z tym istnieje kilka interesujących różnic między API do zapisywania/ładowania w TensorFlow.js i Keras. Zobacz nasz samouczek dotyczący zapisywania i ładowania tf.Model , aby uzyskać więcej informacji.
Użyj fitDataset()
do trenowania modeli przy użyciu obiektów tf.data.Dataset
W tf.keras TensorFlow w Pythonie model można trenować przy użyciu obiektu Dataset . Metoda fit()
modelu bezpośrednio akceptuje taki obiekt. Model TensorFlow.js można również wytrenować za pomocą odpowiednika JavaScript obiektów Dataset (zobacz dokumentację tf.data API w TensorFlow.js ). Jednak w przeciwieństwie do Pythona, szkolenie oparte na Dataset odbywa się za pomocą dedykowanej metody, a mianowicie fitDataset . Metoda fit() jest przeznaczona tylko do uczenia modelu opartego na tensorze.
Zarządzanie pamięcią obiektów warstw i modeli
TensorFlow.js działa na WebGL w przeglądarce, gdzie wagi obiektów Layer i Model są wspierane przez tekstury WebGL. Jednak WebGL nie ma wbudowanej obsługi wyrzucania śmieci. Obiekty Layer i Model wewnętrznie zarządzają pamięcią tensorową użytkownika podczas wnioskowania i wywołań uczących. Ale pozwalają również użytkownikowi na ich utylizację w celu zwolnienia zajmowanej przez nie pamięci WebGL. Jest to przydatne w przypadkach, gdy wiele instancji modelu jest tworzonych i zwalnianych w ramach pojedynczego ładowania strony. Aby usunąć obiekt Layer lub Model, użyj metody dispose()
.