Format SavedModel TensorFlow 2 to zalecany sposób udostępniania wstępnie wytrenowanych modeli i fragmentów modeli w TensorFlow Hub. Zastępuje starszy format TF1 Hub i zawiera nowy zestaw interfejsów API.
Na tej stronie wyjaśniono, jak ponownie wykorzystać TF2 SavedModels w programie TensorFlow 2 z niskopoziomowym interfejsem API hub.load()
i jego opakowaniem hub.KerasLayer
. (Zazwyczaj hub.KerasLayer
łączy się z innymi tf.keras.layers
w celu zbudowania modelu Keras lub model_fn
estymatora TF2). Te interfejsy API mogą również ładować starsze modele w formacie TF1 Hub, w pewnych granicach, patrz przewodnik po zgodności .
Użytkownicy TensorFlow 1 mogą zaktualizować do TF 1.15, a następnie korzystać z tych samych interfejsów API. Starsze wersje TF1 nie działają.
Korzystanie z SavedModels z TF Hub
Korzystanie z SavedModel w Keras
Keras to interfejs API wysokiego poziomu TensorFlow do tworzenia modeli głębokiego uczenia się poprzez komponowanie obiektów warstwy Keras. Biblioteka tensorflow_hub
udostępnia klasę hub.KerasLayer
, która jest inicjowana adresem URL (lub ścieżką systemu plików) SavedModel, a następnie udostępnia obliczenia z SavedModel, w tym jego wstępnie wyszkolone wagi.
Oto przykład użycia wstępnie wyszkolonego osadzania tekstu:
import tensorflow as tf
import tensorflow_hub as hub
hub_url = "https://tfhub.dev/google/nnlm-en-dim128/2"
embed = hub.KerasLayer(hub_url)
embeddings = embed(["A long sentence.", "single-word", "http://example.com"])
print(embeddings.shape, embeddings.dtype)
Na tej podstawie można zbudować klasyfikator tekstu w zwykły sposób Keras:
model = tf.keras.Sequential([
embed,
tf.keras.layers.Dense(16, activation="relu"),
tf.keras.layers.Dense(1, activation="sigmoid"),
])
Colab dotyczący klasyfikacji tekstu jest kompletnym przykładem trenowania i oceniania takiego klasyfikatora.
Wagi modeli w hub.KerasLayer
są domyślnie ustawione na niemożliwe do przeszkolenia. Zobacz sekcję dotyczącą dostrajania poniżej, aby dowiedzieć się, jak to zmienić. Wagi są współdzielone pomiędzy wszystkimi aplikacjami tego samego obiektu warstwy, jak zwykle w Keras.
Używanie zapisanego modelu w estymatorze
Użytkownicy interfejsu API estymatora TensorFlow do szkolenia rozproszonego mogą używać SavedModels z TF Hub, zapisując swój model_fn
w kategoriach hub.KerasLayer
wśród innych tf.keras.layers
.
Za kulisami: pobieranie i buforowanie SavedModel
Użycie SavedModel z TensorFlow Hub (lub innych serwerów HTTPS, które implementują jego protokół hostingu ) powoduje pobranie go i dekompresję do lokalnego systemu plików, jeśli jeszcze go nie ma. Można ustawić zmienną środowiskową TFHUB_CACHE_DIR
aby zastąpić domyślną tymczasową lokalizację do buforowania pobranych i nieskompresowanych zapisanych modeli. Aby uzyskać szczegółowe informacje, zobacz Buforowanie .
Korzystanie z SavedModel w niskopoziomowym TensorFlow
Uchwyty modelowe
SavedModels można załadować z określonego handle
, gdzie handle
jest ścieżka systemu plików, prawidłowy adres URL modelu TFhub.dev (np. „https://tfhub.dev/…”). Adresy URL Kaggle Models odzwierciedlają uchwyty TFhub.dev zgodnie z naszymi Warunkami i licencją powiązaną z zasobami modelu, np. „https://www.kaggle.com/…”. Uchwyty z Kaggle Models są odpowiednikiem odpowiadającego im uchwytu TFhub.dev.
Funkcja hub.load(handle)
pobiera i dekompresuje SavedModel (chyba że handle
jest już ścieżką systemu plików), a następnie zwraca wynik załadowania go za pomocą wbudowanej funkcji TensorFlow tf.saved_model.load()
. Dlatego hub.load()
może obsłużyć każdy prawidłowy SavedModel (w przeciwieństwie do swojego poprzednika hub.Module
dla TF1).
Temat zaawansowany: czego można oczekiwać od SavedModel po załadowaniu
W zależności od zawartości SavedModel wynik obj = hub.load(...)
można wywołać na różne sposoby (jak wyjaśniono znacznie bardziej szczegółowo w Przewodniku SavedModel TensorFlow:
Podpisy obsługujące SavedModel (jeśli istnieją) są reprezentowane jako słownik konkretnych funkcji i można je wywołać w ten sposób
tensors_out = obj.signatures["serving_default"](**tensors_in)
, ze słownikami tensorów kluczowanymi przez odpowiednie dane wejściowe i wyjściowe nazwiska i z zastrzeżeniem ograniczeń dotyczących kształtu i typu podpisu.Metody
@tf.function
-decorated zapisanego obiektu (jeśli istnieją) są przywracane jako obiekty tf.function, które można wywołać za pomocą wszystkich kombinacji argumentów Tensor i innych niż Tensor, dla których funkcja tf.function została prześledzona przed zapisaniem. W szczególności, jeśli istnieje metodaobj.__call__
z odpowiednimi śladami, samobj
można wywołać podobnie jak funkcję Pythona. Prosty przykład może wyglądać następująco:output_tensor = obj(input_tensor, training=False)
.
Pozostawia to ogromną swobodę w interfejsach, które SavedModels może wdrożyć. Interfejs Reusable SavedModels dla obj
ustanawia konwencje takie, że kod klienta, w tym adaptery takie jak hub.KerasLayer
, wie, jak używać SavedModel.
Niektóre SavedModels mogą nie być zgodne z tą konwencją, zwłaszcza całe modele, które nie są przeznaczone do ponownego użycia w większych modelach i zawierają jedynie podpisy służące do obsługi.
Zmienne, które można wytrenować w SavedModel, są ponownie ładowane jako możliwe do wyszkolenia, a tf.GradientTape
domyślnie je obejrzy. Zobacz sekcję dotyczącą dostrajania poniżej, aby poznać pewne zastrzeżenia i na początek rozważ uniknięcie tego. Nawet jeśli chcesz dostroić, możesz sprawdzić, czy obj.trainable_variables
zaleca ponowne uczenie tylko podzbioru pierwotnie możliwych do wytrenowania zmiennych.
Tworzenie zapisanych modeli dla TF Hub
Przegląd
SavedModel to standardowy format serializacji TensorFlow dla przeszkolonych modeli lub fragmentów modelu. Przechowuje wyszkolone wagi modelu wraz z dokładnymi operacjami TensorFlow w celu przeprowadzenia obliczeń. Można go używać niezależnie od kodu, który go utworzył. W szczególności można go ponownie wykorzystać w różnych interfejsach API wysokiego poziomu do budowania modeli, takich jak Keras, ponieważ operacje TensorFlow są ich wspólnym językiem podstawowym.
Oszczędzanie przed Kerasem
Począwszy od TensorFlow 2, tf.keras.Model.save()
i tf.keras.models.save_model()
domyślnie przyjmują format SavedModel (nie HDF5). Powstałe SavedModels, których można używać z hub.load()
, hub.KerasLayer
i podobnymi adapterami dla innych interfejsów API wysokiego poziomu, gdy tylko staną się dostępne.
Aby udostępnić kompletny model Keras, po prostu zapisz go za pomocą include_optimizer=False
.
Aby udostępnić fragment Modelu Keras, uczyń go samym w sobie Modelem, a następnie zapisz go. Możesz albo ułożyć kod w ten sposób od początku....
piece_to_share = tf.keras.Model(...)
full_model = tf.keras.Sequential([piece_to_share, ...])
full_model.fit(...)
piece_to_share.save(...)
...lub wytnij fragment, który chcesz udostępnić po fakcie (jeśli pasuje do warstw całego modelu):
full_model = tf.keras.Model(...)
sharing_input = full_model.get_layer(...).get_output_at(0)
sharing_output = full_model.get_layer(...).get_output_at(0)
piece_to_share = tf.keras.Model(sharing_input, sharing_output)
piece_to_share.save(..., include_optimizer=False)
TensorFlow Models w GitHub korzysta z pierwszego podejścia dla BERT (patrz nlp/tools/export_tfhub_lib.py , zwróć uwagę na podział pomiędzy core_model
do eksportu i pretrainer
do przywracania punktu kontrolnego) i drugiego podejścia dla ResNet (patrz dziedzictwo/image_classification/tfhub_export.py ).
Zapisywanie z niskiego poziomu TensorFlow
Wymaga to dobrej znajomości Przewodnika SavedModel TensorFlow.
Jeśli chcesz zapewnić coś więcej niż tylko podpis obsługujący, powinieneś zaimplementować interfejs Reusable SavedModel . Koncepcyjnie tak to wygląda
class MyMulModel(tf.train.Checkpoint):
def __init__(self, v_init):
super().__init__()
self.v = tf.Variable(v_init)
self.variables = [self.v]
self.trainable_variables = [self.v]
self.regularization_losses = [
tf.function(input_signature=[])(lambda: 0.001 * self.v**2),
]
@tf.function(input_signature=[tf.TensorSpec(shape=None, dtype=tf.float32)])
def __call__(self, inputs):
return tf.multiply(inputs, self.v)
tf.saved_model.save(MyMulModel(2.0), "/tmp/my_mul")
layer = hub.KerasLayer("/tmp/my_mul")
print(layer([10., 20.])) # [20., 40.]
layer.trainable = True
print(layer.trainable_weights) # [2.]
print(layer.losses) # 0.004
Dostrajanie
Uczenie już wytrenowanych zmiennych zaimportowanego SavedModel wraz ze zmienną otaczającego go modelu nazywa się dostrajaniem SavedModel. Może to skutkować lepszą jakością, ale często powoduje, że szkolenie jest bardziej wymagające (może zająć więcej czasu, w większym stopniu zależeć od optymalizatora i jego hiperparametrów, zwiększać ryzyko nadmiernego dopasowania i wymagać powiększenia zbioru danych, szczególnie w przypadku CNN). Radzimy konsumentom SavedModel, aby zastanowili się nad dostrojeniem dopiero po ustaleniu dobrego programu szkoleniowego i tylko wtedy, gdy wydawca SavedModel to zaleca.
Dostrajanie zmienia „ciągłe” parametry modelu, które są szkolone. Nie zmienia to zakodowanych na stałe transformacji, takich jak tokenizacja wprowadzanego tekstu i mapowanie tokenów na odpowiadające im wpisy w macierzy osadzania.
Dla konsumentów SavedModel
Tworzenie hub.KerasLayer
KerasLayer like
layer = hub.KerasLayer(..., trainable=True)
umożliwia dostrojenie SavedModel załadowanego przez warstwę. Dodaje możliwe do trenowania ciężary i regulatory ciężaru zadeklarowane w SavedModel do modelu Keras i uruchamia obliczenia SavedModel w trybie treningowym (pomyśl o rezygnacji itp.).
Colab dotyczący klasyfikacji obrazów zawiera kompleksowy przykład z opcjonalnym dostrojeniem.
Ponowny eksport wyniku dostrajania
Zaawansowani użytkownicy mogą chcieć zapisać wyniki dostrajania z powrotem w SavedModel, którego można użyć zamiast oryginalnie załadowanego. Można to zrobić za pomocą kodu takiego jak
loaded_obj = hub.load("https://tfhub.dev/...")
hub_layer = hub.KerasLayer(loaded_obj, trainable=True, ...)
model = keras.Sequential([..., hub_layer, ...])
model.compile(...)
model.fit(...)
export_module_dir = os.path.join(os.getcwd(), "finetuned_model_export")
tf.saved_model.save(loaded_obj, export_module_dir)
Dla twórców SavedModel
Tworząc SavedModel do udostępniania w TensorFlow Hub, zastanów się z wyprzedzeniem, czy i w jaki sposób konsumenci powinni go dostroić, a także podaj wskazówki w dokumentacji.
Zapisywanie z modelu Keras powinno sprawić, że cała mechanika dostrajania będzie działać (oszczędzanie strat związanych z regularyzacją wagi, deklarowanie zmiennych możliwych do wyszkolenia, śledzenie __call__
zarówno dla training=True
, jak i training=False
itp.)
Wybierz interfejs modelu, który dobrze współpracuje z przepływem gradientowym, np. logity wyjściowe zamiast prawdopodobieństw softmax lub przewidywań górnego k.
Jeśli w modelu zastosowano porzucanie, normalizację wsadową lub podobne techniki szkoleniowe obejmujące hiperparametry, ustaw je na wartości, które mają sens w przypadku wielu oczekiwanych problemów docelowych i rozmiarów partii. (W chwili pisania tego tekstu oszczędzanie w Keras nie ułatwia konsumentom dostosowania ich.)
Zapisywane są regulatory wagi na poszczególnych warstwach (wraz z ich współczynnikami siły regularyzacji), ale regularyzacja wagi z poziomu optymalizatora (np. tf.keras.optimizers.Ftrl.l1_regularization_strength=...)
) zostaje utracona. Odpowiednio poinformuj konsumentów o swoim SavedModel.