Dziękujemy za zapoznanie się z Google I/O. Zobacz wszystkie sesje na żądanie Oglądaj na żądanie

Zapisane modele wielokrotnego użytku

Wstęp

TensorFlow Hub obsługuje między innymi SavedModels dla TensorFlow 2. Można je ponownie załadować do programu w języku Python za pomocą obj = hub.load(url) [ dowiedz się więcej ]. Zwrócony obiekt jest wynikiem obj tf.saved_model.load() (zobacz przewodnik po SavedModel TensorFlow ). Ten obiekt może mieć dowolne atrybuty, takie jak tf.functions, tf.Variables (inicjowane z ich wcześniej wytrenowanych wartości), inne zasoby i rekurencyjnie więcej takich obiektów.

Na tej stronie opisano interfejs, który ma zostać zaimplementowany przez załadowany obiekt w celu ponownego użycia w programie obj w języku Python. SavedModels zgodne z tym interfejsem są nazywane Reusable SavedModels .

Ponowne użycie oznacza zbudowanie większego modelu wokół obj , w tym możliwość jego dopracowania. Dostrajanie oznacza dalsze trenowanie ciężarków w obciążonym obj w ramach otaczającego modelu. Funkcja strat i optymalizator są określane przez otaczający model; obj definiuje tylko mapowanie aktywacji wejścia na wyjście („przejście do przodu”), prawdopodobnie z uwzględnieniem technik, takich jak przerwanie lub normalizacja wsadowa.

Zespół TensorFlow Hub zaleca wdrożenie interfejsu SavedModel wielokrotnego użytku we wszystkich SavedModelach, które mają być ponownie używane w powyższym znaczeniu. Wiele narzędzi z biblioteki tensorflow_hub , w szczególności hub.KerasLayer , wymaga zaimplementowania SavedModels.

Relacja do SignatureDefs

Ten interfejs pod względem tf.functions i innych funkcji TF2 jest niezależny od sygnatur SavedModel, które były dostępne od TF1 i nadal są używane w TF2 do wnioskowania (takiego jak wdrażanie SavedModels w TF Serving lub TF Lite). Sygnatury do wnioskowania nie są wystarczająco wyraziste, aby wspierać precyzyjne dostrajanie, a tf.function zapewnia bardziej naturalny i wyrazisty interfejs API Pythona dla ponownie używanego modelu.

Związek z bibliotekami do budowania modeli

Zapisany model wielokrotnego użytku wykorzystuje tylko prymitywy TensorFlow 2, niezależnie od konkretnej biblioteki do budowania modeli, takiej jak Keras czy Sonnet. Ułatwia to ponowne wykorzystanie w bibliotekach do budowania modeli, bez zależności od oryginalnego kodu do budowania modeli.

Konieczna będzie pewna adaptacja, aby załadować zapisane modele wielokrotnego użytku lub zapisać je z dowolnej biblioteki do budowania modeli. W przypadku Keras ładowanie zapewnia hub.KerasLayer , a wbudowane w Keras zapisywanie w formacie SavedModel zostało przeprojektowane dla TF2 w celu zapewnienia nadzbioru tego interfejsu (patrz RFC z maja 2019 r.).

Relacja do specyficznych dla zadań „Powszechnych interfejsów API SavedModel”

Definicja interfejsu na tej stronie dopuszcza dowolną liczbę i typ wejść i wyjść. Wspólne interfejsy API SavedModel dla TF Hub udoskonalają ten ogólny interfejs za pomocą konwencji użytkowania dla określonych zadań, aby modele były łatwo wymienialne.

Definicja interfejsu

Atrybuty

SavedModel wielokrotnego użytku to SavedModel TensorFlow 2 taki, że obj = tf.saved_model.load(...) zwraca obiekt, który ma następujące atrybuty

  • __call__ . Wymagany. Funkcja tf. implementująca obliczenia modelu („przebieg w przód”) zgodnie z poniższą specyfikacją.

  • variables : Lista obiektów tf.Variable, zawierająca listę wszystkich zmiennych używanych przez każde możliwe wywołanie __call__ , w tym zarówno te, które można trenować, jak i te, których nie można trenować.

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

  • trainable_variables : Lista obiektów tf.Variable, dla których v.trainable jest prawdziwe dla wszystkich elementów. Te zmienne muszą być podzbiorem variables . Są to zmienne, które mają być trenowane podczas dostrajania obiektu. Twórca SavedModel może w tym miejscu pominąć niektóre zmienne, które pierwotnie można było trenować, aby wskazać, że nie należy ich modyfikować 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 pobiera zero danych wejściowych i zwraca pojedynczy skalarny tensor zmiennoprzecinkowy. W celu dokładnego dostrojenia zaleca się użytkownikowi SavedModel uwzględnienie tych warunków jako dodatkowych warunków regularyzacji w stracie (w najprostszym przypadku bez dalszego skalowania). Zazwyczaj są one używane do reprezentowania regulatorów wagi. (Z powodu braku danych wejściowych te funkcje tf. nie mogą wyrażać regulatoró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 zalecić regularyzacji wagi.

Funkcja __call__

Obiekt Restored obj ma atrybut obj obj.__call__ , który jest przywróconą funkcją tf. i umożliwia wywoływanie obiektu w następujący sposób.

Streszczenie (pseudo-kod):

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

Argumenty

Argumenty są następujące.

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

    • pojedynczy tensor dla jednego wejścia,
    • lista Tensorów dla uporządkowanej sekwencji nienazwanych wejść,
    • dyktat tensorów kluczowany przez określony zestaw nazw wejściowych.

    (Przyszłe wersje tego interfejsu mogą pozwolić na bardziej ogólne zagnieżdżenia.) Twórca SavedModel wybiera jeden z nich oraz kształty i typy tensorów. Tam, gdzie jest to przydatne, niektóre wymiary kształtu powinny być niezdefiniowane (zwłaszcza wielkość partii).

  • Może istnieć opcjonalne training w zakresie argumentów słów kluczowych, które akceptuje wartość logiczną Pythona, True lub False . Wartość domyślna to False . Jeśli model obsługuje precyzyjne dostrajanie, a jego obliczenia różnią się między nimi (np. w przypadku odrzucania i normalizacji wsadowej), to rozróżnienie jest realizowane za pomocą tego argumentu. W przeciwnym razie ten argument może być nieobecny.

    Nie jest wymagane, aby __call__ akceptował argument training o wartości Tensor. Na dzwoniącym spoczywa obowiązek użycia tf.cond() w razie potrzeby do rozsyłania między nimi.

  • Twórca SavedModel może zaakceptować więcej opcjonalnych kwargs o określonych nazwach.

    • W przypadku argumentów o wartości Tensor twórca SavedModel definiuje ich dopuszczalne typy i kształty. tf.function akceptuje domyślną wartość Pythona dla argumentu, który jest śledzony za pomocą danych wejściowych tf.TensorSpec. Takich argumentów można użyć, aby umożliwić dostosowanie hiperparametrów liczbowych związanych z __call__ (np. wskaźnik rezygnacji).

    • W przypadku argumentów z wartościami Pythona 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 udostępniać ślady dla wszystkich dopuszczalnych kombinacji argumentów. Przerzucanie training między True a False nie może zmieniać dopuszczalności argumentów.

Wynik

outputs z wywołania obj mogą być

  • jeden Tensor dla jednego wyjścia,
  • lista Tensorów dla uporządkowanej sekwencji nienazwanych wyjść,
  • dyktat tensorów kluczowany przez określony zestaw nazw wyjściowych.

(Przyszłe wersje tego interfejsu mogą zezwolić na bardziej ogólne zagnieżdżenia.) Zwracany typ może się różnić w zależności od wartości kwarg Pythona. Pozwala to na flagi generujące dodatkowe wyjścia. Kreator SavedModel definiuje wyjściowe typy i kształty oraz ich zależność od danych wejściowych.

Nazwane wywołania

ZapisanyModel wielokrotnego użytku może udostępniać wiele elementów modelu w sposób opisany powyżej, umieszczając je w nazwanych obiektach podrzędnych, na przykład obj.foo , obj.bar i tak dalej. Każdy obiekt podrzędny zapewnia metodę __call__ i atrybuty pomocnicze dotyczące zmiennych itp. specyficzne dla tego elementu modelu. W powyższym przykładzie byłyby to obj.foo.__call__ , obj.foo.variables i tak dalej.

Zauważ, że ten interfejs nie obejmuje podejścia polegającego na dodawaniu gołej funkcji tf. bezpośrednio jako tf.foo .

Oczekuje się, że użytkownicy wielokrotnego użytku SavedModels będą obsługiwać tylko jeden poziom zagnieżdżania ( obj.bar ale nie obj.bar.baz ). (Przyszłe wersje tego interfejsu mogą pozwolić na głębsze zagnieżdżanie i mogą odstąpić od wymogu, aby obiekt najwyższego poziomu był wywoływalny).

Uwagi końcowe

Relacja z interfejsami API w procesie

Ten dokument opisuje interfejs klasy Python, który składa się z prymitywów, takich jak tf.function i tf.Variable, które przetrwają podróż w obie strony przez serializację za pośrednictwem tf.saved_model.save() i tf.saved_model.load() . Jednak interfejs był już obecny w oryginalnym obiekcie, który został przekazany do tf.saved_model.save() . Dostosowanie do tego interfejsu umożliwia wymianę elementów modelu między interfejsami API do budowania modeli w ramach jednego programu TensorFlow.