Zapisane modele wielokrotnego użytku

Wstęp

TensorFlow Hub hostuje obiekty SavedModels dla TensorFlow 2, a także inne zasoby. Można je załadować z powrotem do programu Python poleceniem obj = hub.load(url) [ dowiedz się więcej ]. Zwrócony obj jest wynikiem tf.saved_model.load() (zobacz przewodnik TensorFlow po obiektach SavedModel ). Obiekt ten może zawierać dowolne atrybuty, takie jak tf.functions, tf.Variables (zainicjowane z ich wstępnie wytrenowanych wartości), inne zasoby i, rekurencyjnie, więcej tego typu obiektów.

Ta strona opisuje interfejs, który ma zostać zaimplementowany przez załadowany obj w celu ponownego wykorzystania w programie TensorFlow Python. Modele zapisane (SavedModels) zgodne z tym interfejsem nazywane są modelami wielokrotnego użytku (Reusable SavedModels ).

Ponowne wykorzystanie oznacza zbudowanie większego modelu wokół obj , w tym możliwość jego precyzyjnego dostrojenia. Dostrajanie oznacza dalsze trenowanie wag w załadowanym obj jako części otaczającego modelu. Funkcja straty i optymalizator są określane przez otaczający model; obj definiuje jedynie mapowanie aktywacji wejściowych na wyjściowe („przejście do przodu”), potencjalnie obejmując techniki takie jak porzucanie lub normalizacja wsadowa.

Zespół TensorFlow Hub zaleca implementację interfejsu Reusable SavedModel we wszystkich SavedModelach, które mają być ponownie wykorzystywane w powyższym sensie. Wiele narzędzi z biblioteki tensorflow_hub , w szczególności hub.KerasLayer , wymaga SavedModelów do jego implementacji.

Relacja z SignatureDefs

Ten interfejs, jeśli chodzi o tf.functions i inne funkcje TF2, jest niezależny od sygnatur SavedModel, które były dostępne od TF1 i nadal są używane w TF2 do inferencji (na przykład do wdrażania SavedModel w TF Serving lub TF Lite). Sygnatury do inferencji nie są wystarczająco ekspresyjne, aby umożliwić precyzyjne dostrajanie, a tf.function zapewnia bardziej naturalne i ekspresyjne API Pythona dla ponownie wykorzystywanego modelu.

Relacja z bibliotekami do budowania modeli

Model SavedModel wielokrotnego użytku wykorzystuje wyłącznie prymitywy TensorFlow 2, niezależnie od konkretnej biblioteki do budowania modeli, takiej jak Keras czy Sonnet. Ułatwia to ponowne wykorzystanie w różnych bibliotekach do budowania modeli, bez zależności od oryginalnego kodu do budowania modeli.

Wczytanie wielokrotnego użytku modeli SavedModels do dowolnej biblioteki budowania modeli lub zapisanie ich z niej będzie wymagało pewnej adaptacji. W przypadku Keras ładowanie zapewnia hub.KerasLayer , a wbudowany w Keras zapis w formacie SavedModel został przeprojektowany na potrzeby TF2 w celu zapewnienia rozszerzenia tego interfejsu (patrz RFC z maja 2019 r.).

Relacja ze specyficznymi dla zadań „wspólnymi interfejsami API SavedModel”

Definicja interfejsu na tej stronie dopuszcza dowolną liczbę i typ danych wejściowych i wyjściowych. Wspólne API SavedModel dla TF Hub udoskonalają ten ogólny interfejs, wprowadzając konwencje użycia dla konkretnych zadań, aby ułatwić wymienność modeli.

Definicja interfejsu

Atrybuty

Model zapisany wielokrotnego użytku to model zapisany TensorFlow 2, w którym obj = tf.saved_model.load(...) zwraca obiekt, który ma następujące atrybuty

  • __call__ . Wymagane. Funkcja tf.function implementująca obliczenia modelu („przejście do przodu”), zgodnie z poniższą specyfikacją.

  • variables : Lista obiektów tf.Variable zawierająca wszystkie zmienne używane przez dowolne wywołanie __call__ , w tym zmienne możliwe do trenowania i niemożliwe do trenowania.

    Tę listę można pominąć, jeśli jest pusta.

  • trainable_variables : Lista obiektów tf.Variable, dla których v.trainable ma wartość true dla wszystkich elementów. Te zmienne muszą być podzbiorem variables . Są to zmienne, które mają zostać wytrenowane podczas dostrajania obiektu. Twórca SavedModel może pominąć niektóre zmienne, które pierwotnie można było wytrenować, aby wskazać, że nie powinny być modyfikowane podczas dostrajania.

    Tę listę można pominąć, jeśli jest pusta, w szczególności jeśli SavedModel nie obsługuje dostrajania.

  • regularization_losses : Lista funkcji tf.functions, z których każda przyjmuje zerowe dane wejściowe i zwraca pojedynczy skalarny tensor zmiennoprzecinkowy. W celu dostrojenia, użytkownikowi SavedModel zaleca się uwzględnienie ich jako dodatkowych członów regularyzacji w stracie (w najprostszym przypadku bez dalszego skalowania). Zazwyczaj służą one do reprezentowania regularyzatorów wagowych. (Z powodu braku danych wejściowych te funkcje tf.functions nie mogą wyrażać regularyzatorów aktywności).

    Tę listę można pominąć, jeśli jest pusta, w szczególności jeśli SavedModel nie obsługuje dostrajania lub nie chce zalecać regularyzacji wagi.

Funkcja __call__

Przywrócony obj SavedModel ma atrybut obj.__call__ , który jest przywróconą funkcją tf.function i umożliwia wywołanie obj w następujący sposób.

Streszczenie (pseudokod):

outputs = obj(inputs, trainable=..., **kwargs)

Argumenty

Argumenty są następujące.

  • Istnieje jeden argument pozycyjny, wymagany z partią aktywacji wejściowych SavedModel. Jego typ jest jednym z

    • pojedynczy tensor dla pojedynczego wejścia,
    • lista tensorów dla uporządkowanej sekwencji nienazwanych danych wejściowych,
    • słownik tensorów opartych na określonym zestawie nazw wejściowych.

    (Przyszłe wersje tego interfejsu mogą dopuszczać bardziej ogólne gniazda). Kreator SavedModel wybiera jeden z tych elementów, kształty tensora i typy danych. W razie potrzeby niektóre wymiary kształtu powinny być niezdefiniowane (zwłaszcza rozmiar partii).

  • Może istnieć opcjonalny training słowa kluczowego, który akceptuje wartość logiczną Pythona: True (Prawda) lub False ). Wartością domyślną jest False . Jeśli model obsługuje dostrajanie, a jego obliczenia różnią się między nimi (np. w przypadku normalizacji porzucania i wsadowej), to rozróżnienie jest implementowane za pomocą tego argumentu. W przeciwnym razie argument ten może być nieobecny.

    Nie jest wymagane, aby __call__ akceptował argument training o wartościach tensora. W razie potrzeby do rozsyłania między nimi należy użyć tf.cond() .

  • Twórca SavedModel może zdecydować się na zaakceptowanie większej liczby opcjonalnych kwargs o określonych nazwach.

    • W przypadku argumentów o wartościach tensorowych, twórca SavedModel definiuje ich dopuszczalne typy danych i kształty. tf.function akceptuje domyślną wartość Pythona dla argumentu śledzonego za pomocą danych wejściowych tf.TensorSpec. Takie argumenty mogą być używane do dostosowywania hiperparametrów numerycznych zaangażowanych w __call__ (np. wskaźnik porzucania).

    • W przypadku argumentów o wartościach w Pythonie, twórca SavedModel definiuje ich dopuszczalne wartości. Takie argumenty mogą być używane jako flagi do dokonywania dyskretnych wyborów w śledzonej funkcji (należy jednak pamiętać o kombinatorycznej eksplozji śladów).

Przywrócona funkcja __call__ musi zapewniać ślady dla wszystkich dopuszczalnych kombinacji argumentów. Zmiana wartości training między True i False nie może zmieniać dopuszczalności argumentów.

Wynik

outputs wywołania obj mogą być

  • pojedynczy tensor dla pojedynczego wyjścia,
  • lista tensorów dla uporządkowanej sekwencji nienazwanych wyjść,
  • słownik tensorów kluczowanych przez określony zestaw nazw wyjściowych.

(Przyszłe wersje tego interfejsu mogą dopuszczać bardziej ogólne zagnieżdżenia). Typ zwracany może się różnić w zależności od wartości zmiennych kwargs w Pythonie. Pozwala to na generowanie dodatkowych wyników przez flagi. Kreator SavedModel definiuje typy danych i kształty danych wyjściowych oraz ich zależność od danych wejściowych.

Nazwane obiekty wywoływalne

Wielokrotnego użytku SavedModel może dostarczać wiele elementów modelu w sposób opisany powyżej, umieszczając je w nazwanych podobiektach, na przykład obj.foo , obj.bar itd. Każdy podobiekt udostępnia metodę __call__ oraz atrybuty pomocnicze dotyczące zmiennych itp. specyficznych dla danego elementu modelu. W powyższym przykładzie byłyby to obj.foo.__call__ , obj.foo.variables itd.

Należy pamiętać, że ten interfejs nie obejmuje podejścia polegającego na dodaniu czystej funkcji tf.function bezpośrednio jako tf.foo .

Od użytkowników Reusable SavedModels oczekuje się obsługi tylko jednego poziomu zagnieżdżenia ( obj.bar , ale nie obj.bar.baz ). (Przyszłe wersje tego interfejsu mogą umożliwiać głębsze zagnieżdżanie i mogą znieść wymóg, aby obiekt najwyższego poziomu sam był wywoływalny).

Uwagi końcowe

Relacja z interfejsami API w procesie

Niniejszy dokument opisuje interfejs klasy Pythona, który składa się z prymitywów, takich jak tf.function i tf.Variable, które przechodzą przez proces serializacji za pomocą tf.saved_model.save() i tf.saved_model.load() . Interfejs ten był jednak już obecny w oryginalnym obiekcie przekazanym do tf.saved_model.save() . Adaptacja do tego interfejsu umożliwia wymianę elementów modelu między interfejsami API do budowania modeli w ramach jednego programu TensorFlow.