Modele i warstwy

W uczeniu maszynowym model to funkcja z możliwymi do nauczenia się parametrami , która odwzorowuje dane wejściowe na dane wyjściowe. Optymalne parametry uzyskuje się poprzez uczenie modelu na danych. Dobrze wytrenowany model zapewni dokładne mapowanie od wejścia do pożądanego wyniku.

W TensorFlow.js istnieją dwa sposoby tworzenia modelu uczenia maszynowego:

  1. przy użyciu interfejsu API Layers, w którym budujesz model przy użyciu warstw .
  2. używanie Core API z operacjami niższego poziomu, takimi jak tf.matMul() , tf.add() itp.

Najpierw przyjrzymy się interfejsowi Layers API, który jest interfejsem API wyższego poziomu do budowania modeli. Następnie pokażemy, jak zbudować ten sam model przy użyciu Core API.

Tworzenie modeli za pomocą interfejsu Layers API

Istnieją dwa sposoby tworzenia modelu przy użyciu interfejsu Layers API: model sekwencyjny i model funkcjonalny . W następnych dwóch sekcjach przyjrzymy się bliżej każdemu typowi.

Model sekwencyjny

Najpopularniejszym typem modelu jest model Sequential , który jest liniowym stosem warstw. Możesz utworzyć model Sequential , przekazując listę warstw do funkcji sequential() :

const model = tf.sequential({
 layers: [
   tf.layers.dense({inputShape: [784], units: 32, activation: 'relu'}),
   tf.layers.dense({units: 10, activation: 'softmax'}),
 ]
});

Lub za pomocą metody add() :

const model = tf.sequential();
model.add(tf.layers.dense({inputShape: [784], units: 32, activation: 'relu'}));
model.add(tf.layers.dense({units: 10, activation: 'softmax'}));

WAŻNE: Pierwsza warstwa modelu wymaga inputShape . Upewnij się, że wykluczyłeś rozmiar partii podczas podawania inputShape . Na przykład, jeśli planujesz podać tensory modelu o kształcie [B, 784] , gdzie B może mieć dowolny rozmiar wsadowy, podczas tworzenia modelu określ inputShape jako [784] .

Dostęp do warstw modelu można uzyskać poprzez model.layers , a dokładniej model.inputLayers i model.outputLayers .

Model funkcjonalny

Innym sposobem utworzenia LayersModel jest użycie funkcji tf.model() . Kluczowa różnica między tf.model() i tf.sequential() polega na tym, że tf.model() pozwala na utworzenie dowolnego wykresu warstw, o ile nie mają one cykli.

Oto fragment kodu, który definiuje ten sam model co powyżej, przy użyciu interfejsu API tf.model() :

// Create an arbitrary graph of layers, by connecting them
// via the apply() method.
const input = tf.input({shape: [784]});
const dense1 = tf.layers.dense({units: 32, activation: 'relu'}).apply(input);
const dense2 = tf.layers.dense({units: 10, activation: 'softmax'}).apply(dense1);
const model = tf.model({inputs: input, outputs: dense2});

Wywołujemy apply() na każdej warstwie, aby połączyć ją z wyjściem innej warstwy. Wynikiem apply() w tym przypadku jest SymbolicTensor , który działa jak Tensor , ale bez żadnych konkretnych wartości.

Zauważ, że w przeciwieństwie do modelu sekwencyjnego, tworzymy SymbolicTensor za pomocą tf.input() zamiast udostępniać inputShape pierwszej warstwie.

apply() może również dać ci konkretny Tensor , jeśli przekażesz mu konkretny Tensor :

const t = tf.tensor([-2, 1, 0, 5]);
const o = tf.layers.activation({activation: 'relu'}).apply(t);
o.print(); // [0, 1, 0, 5]

Może to być przydatne podczas testowania izolowanych warstw i sprawdzania ich wyników.

Podobnie jak w modelu sekwencyjnym, dostęp do warstw modelu można uzyskać poprzez model.layers , a dokładniej model.inputLayers i model.outputLayers .

Walidacja

Zarówno model sekwencyjny, jak i model funkcjonalny są instancjami klasy LayersModel . Jedną z głównych zalet pracy z LayersModel jest sprawdzanie poprawności: zmusza Cię to do określenia kształtu wejściowego i użyje go później do sprawdzenia wprowadzonych danych. LayersModel wykonuje również automatyczne wnioskowanie o kształcie podczas przepływu danych przez warstwy. Znajomość kształtu z góry pozwala modelowi automatycznie utworzyć jego parametry i określić, czy dwie kolejne warstwy nie są ze sobą kompatybilne.

Podsumowanie modelu

Wywołaj model.summary() , aby wydrukować przydatne podsumowanie modelu, które obejmuje:

  • Nazwa i typ wszystkich warstw w modelu.
  • Kształt wyjściowy dla każdej warstwy.
  • Liczba parametrów wagowych każdej warstwy.
  • Jeśli model ma topologię ogólną (omówioną poniżej), dane wejściowe otrzymuje każda warstwa
  • Całkowita liczba możliwych do wyszkolenia i niemożliwych do przeszkolenia parametrów modelu.

Dla modelu, który zdefiniowaliśmy powyżej, otrzymujemy na konsoli następujące dane wyjściowe:

Warstwa (typ) Kształt wyjściowy Parametr #
gęsty_Dense1 (Gęsty) [null,32] 25120
gęsty_Dense2 (Gęsty) [null,10] 330
Łączne parametry: 25450
Parametry możliwe do wytrenowania: 25450
Parametry, których nie można trenować: 0

Zwróć uwagę na wartości null w kształtach wyjściowych warstw: przypomnienie, że model oczekuje, że dane wejściowe będą miały rozmiar partii jako najbardziej zewnętrzny wymiar, co w tym przypadku może być elastyczne ze względu na wartość null .

Serializacja

Jedną z głównych zalet używania LayersModel w porównaniu z interfejsem API niższego poziomu jest możliwość zapisania i załadowania modelu. LayersModel wie o:

  • architekturę modelu, co pozwala na jego ponowne utworzenie.
  • wagi modelu
  • konfiguracja treningu (strata, optymalizator, metryki).
  • stan optymalizatora, umożliwiający wznowienie treningu.

Aby zapisać lub załadować model, wystarczy 1 linia kodu:

const saveResult = await model.save('localstorage://my-model-1');
const model = await tf.loadLayersModel('localstorage://my-model-1');

Powyższy przykład zapisuje model w pamięci lokalnej w przeglądarce. Zobacz model.save() documentation oraz przewodnik dotyczący zapisywania i ładowania , aby dowiedzieć się, jak zapisywać na różnych nośnikach (np. w magazynie plików, IndexedDB , uruchamiać pobieranie przeglądarki itp.).

Warstwy niestandardowe

Warstwy są elementami składowymi modelu. Jeśli Twój model wykonuje obliczenia niestandardowe, możesz zdefiniować warstwę niestandardową, która dobrze współdziała z pozostałymi warstwami. Poniżej definiujemy niestandardową warstwę, która oblicza sumę kwadratów:

class SquaredSumLayer extends tf.layers.Layer {
 constructor() {
   super({});
 }
 // In this case, the output is a scalar.
 computeOutputShape(inputShape) { return []; }

 // call() is where we do the computation.
 call(input, kwargs) { return input.square().sum();}

 // Every layer needs a unique name.
 getClassName() { return 'SquaredSum'; }
}

Aby to przetestować, możemy wywołać metodę apply() z konkretnym tensorem:

const t = tf.tensor([-2, 1, 0, 5]);
const o = new SquaredSumLayer().apply(t);
o.print(); // prints 30

WAŻNE: Jeśli dodasz warstwę niestandardową, utracisz możliwość serializacji modelu.

Tworzenie modeli za pomocą Core API

Na początku tego przewodnika wspomnieliśmy, że istnieją dwa sposoby tworzenia modelu uczenia maszynowego w TensorFlow.js.

Ogólna zasada jest taka, aby zawsze najpierw próbować użyć interfejsu Layers API, ponieważ jest on wzorowany na dobrze przyjętym interfejsie API Keras, który jest zgodny z najlepszymi praktykami i zmniejsza obciążenie poznawcze . Interfejs API Layers oferuje również różne gotowe rozwiązania, takie jak inicjalizacja wagi, serializacja modelu, szkolenie w zakresie monitorowania, przenośność i sprawdzanie bezpieczeństwa.

Możesz chcieć użyć Core API, gdy:

  • Potrzebujesz maksymalnej elastyczności i kontroli.
  • Nie potrzebujesz serializacji lub możesz zaimplementować własną logikę serializacji.

Modele w Core API to po prostu funkcje, które pobierają jeden lub więcej Tensors i zwracają Tensor . Ten sam model, co powyżej, napisany przy użyciu Core API, wygląda następująco:

// The weights and biases for the two dense layers.
const w1 = tf.variable(tf.randomNormal([784, 32]));
const b1 = tf.variable(tf.randomNormal([32]));
const w2 = tf.variable(tf.randomNormal([32, 10]));
const b2 = tf.variable(tf.randomNormal([10]));

function model(x) {
  return x.matMul(w1).add(b1).relu().matMul(w2).add(b2).softmax();
}

Należy pamiętać, że w Core API jesteśmy odpowiedzialni za utworzenie i inicjalizację wag modelu. Każda waga jest poparta Variable , która sygnalizuje TensorFlow.js, że tych tensorów można się nauczyć. Możesz utworzyć Variable za pomocą tf.variable() i przekazać istniejący Tensor .

W tym przewodniku zapoznałeś się z różnymi sposobami tworzenia modelu przy użyciu warstw i podstawowego interfejsu API. Następnie zapoznaj się z przewodnikiem po modelach szkoleniowych , aby dowiedzieć się, jak trenować model.