Zgodność wersji TensorFlow

Ten dokument jest przeznaczony dla użytkowników, którzy potrzebują kompatybilności wstecznej między różnymi wersjami TensorFlow (dla kodu lub danych) oraz dla programistów, którzy chcą modyfikować TensorFlow przy jednoczesnym zachowaniu kompatybilności.

Wersjonowanie semantyczne 2.0

TensorFlow korzysta z wersji Semantic 2.0 ( semver ) dla swojego publicznego interfejsu API. Każda wersja TensorFlow ma postać MAJOR.MINOR.PATCH . Na przykład TensorFlow wersja 1.2.3 ma wersję MAJOR 1, MINOR wersję 2 i PATCH wersję 3. Zmiany w każdym numerze mają następujące znaczenie:

  • WAŻNE : Zmiany potencjalnie niekompatybilne wstecz. Kod i dane, które działały z poprzednią wersją główną, niekoniecznie będą działać z nową wersją. Jednak w niektórych przypadkach istniejące wykresy i punkty kontrolne TensorFlow mogą podlegać migracji do nowszej wersji; zobacz Zgodność wykresów i punktów kontrolnych , aby uzyskać szczegółowe informacje na temat zgodności danych.

  • MINOR : Funkcje kompatybilne wstecz, ulepszenia szybkości itp. Kod i dane, które działały z poprzednią pomniejszą wersją i które zależą wyłącznie od nieeksperymentalnego publicznego API, będą nadal działać bez zmian. Aby uzyskać szczegółowe informacje na temat tego, co jest, a co nie jest publicznym interfejsem API, zobacz temat Zakres usług .

  • PATCH : Poprawki błędów kompatybilne wstecz.

Na przykład w wersji 1.0.0 wprowadzono niezgodne wstecz zmiany z wersji 0.12.1. Jednakże wersja 1.1.1 była wstecznie kompatybilna z wersją 1.0.0.

Co obejmuje

Tylko publiczne interfejsy API TensorFlow są wstecznie kompatybilne z wersjami pomocniczymi i poprawkami. Publiczne interfejsy API składają się z

  • Wszystkie udokumentowane funkcje i klasy Pythona w module tensorflow i jego podmodułach, z wyjątkiem

    • Symbole prywatne: dowolna funkcja, klasa itp., której nazwa zaczyna się od _
    • Symbole eksperymentalne i tf.contrib — szczegółowe informacje znajdują się poniżej .

    Należy pamiętać, że kod w katalogach examples/ i tools/ nie jest dostępny za pośrednictwem modułu Pythona tensorflow i dlatego nie jest objęty gwarancją kompatybilności.

    Jeśli symbol jest dostępny za pośrednictwem modułu Pythona tensorflow lub jego podmodułów, ale nie jest udokumentowany, nie jest uważany za część publicznego interfejsu API.

  • API kompatybilności (w Pythonie moduł tf.compat ). W wersjach głównych możemy udostępnić narzędzia i dodatkowe punkty końcowe, aby pomóc użytkownikom w przejściu do nowej wersji głównej. Te symbole API są przestarzałe i nie są obsługiwane (tzn. nie dodamy żadnych funkcji i nie będziemy naprawiać błędów w inny sposób niż naprawianie luk w zabezpieczeniach), ale objęte są naszymi gwarancjami zgodności.

  • Interfejs API TensorFlow C:

  • Następujące pliki bufora protokołu:

Oddzielny numer wersji dla TensorFlow Lite

Obecnie TensorFlow Lite jest dystrybuowany jako część TensorFlow. Zastrzegamy sobie jednak prawo do wprowadzenia w przyszłych wersjach zmian w interfejsach API TensorFlow Lite według innego harmonogramu niż w przypadku innych interfejsów API TensorFlow, a nawet do przeniesienia TensorFlow Lite do oddzielnej dystrybucji źródłowej i/lub osobnego repozytorium źródłowego niż TensorFlow.

Z tego powodu używamy innego numeru wersji dla TensorFlow Lite ( TFLITE_VERSION_STRING w tensorflow/lite/version.h i TfLiteVersion() w tensorflow/lite/c/c_api.h ) niż dla TensorFlow ( TF_VERSION_STRING w tensorflow/core/public/version.h i TF_Version() w tensorflow/c/c_api.h ). Obecnie te dwa numery wersji mają tę samą wartość. Jednak w przyszłości mogą się one różnić; na przykład możemy zwiększyć główny numer wersji TensorFlow Lite bez zwiększania głównego numeru wersji TensorFlow i odwrotnie.

Powierzchnia API objęta numerem wersji TensorFlow Lite składa się z następujących publicznych interfejsów API:

Symbole eksperymentalne nie są uwzględnione; szczegóły znajdziesz poniżej .

Oddzielny numer wersji dla interfejsów API rozszerzenia TensorFlow Lite

TensorFlow Lite zapewnia interfejsy API języka C umożliwiające rozszerzenie interpretera TensorFlow Lite o „niestandardowe operacje”, które zapewniają zdefiniowane przez użytkownika operacje na wykresie, lub „delegaty”, które umożliwiają delegowanie obliczeń dla wykresu (lub podzbioru wykresu) do niestandardowy backend. Te interfejsy API, które wspólnie nazywamy „interfejsami API rozszerzenia TensorFlow Lite”, wymagają bardziej szczegółowych zależności od niektórych szczegółów implementacji TensorFlow Lite.

Zastrzegamy sobie prawo do wprowadzania w przyszłych wydaniach zmian w tych interfejsach API, potencjalnie włączając zmiany niekompatybilne wstecz, według innego harmonogramu niż w przypadku innych interfejsów API TensorFlow Lite. Dlatego używamy innego numeru wersji dla interfejsów API rozszerzenia TensorFlow Lite niż numery wersji dla TensorFlow Lite lub TensorFlow (które zostały opisane w poprzedniej sekcji). Wprowadzamy kilka nowych interfejsów API w wersji 2.15 TensorFlow Lite, aby uzyskać wersję interfejsów API rozszerzenia TensorFlow Lite ( TFLITE_EXTENSION_APIS_VERSION_STRING w tensorflow/lite/version.h i TfLiteExtensionApisVersion() w tensorflow/lite/c/c_api.h ). Numer wersji interfejsów API rozszerzenia TensorFlow Lite jest obecnie taki sam, jak numer wersji TensorFlow i TensorFlow Lite. Jednak w przyszłości mogą się one różnić; na przykład możemy zwiększyć główny numer wersji interfejsów API rozszerzenia TensorFlow Lite bez zwiększania głównego numeru wersji TensorFlow Lite i odwrotnie.

Powierzchnia API objęta numerem wersji interfejsów API rozszerzenia TensorFlow Lite składa się z następujących publicznych interfejsów API:

Ponownie nie uwzględniono symboli eksperymentalnych; szczegóły znajdziesz poniżej .

Czego nie obejmuje

Niektóre części TensorFlow mogą w dowolnym momencie ulec zmianie w sposób niezgodny wstecz. Obejmują one:

  • Eksperymentalne interfejsy API : aby ułatwić rozwój, niektóre symbole API wyraźnie oznaczone jako eksperymentalne wyłączamy z gwarancji kompatybilności. Gwarancją kompatybilności nie są w szczególności objęte:

    • dowolny symbol w module tf.contrib lub jego podmodułach;
    • dowolny symbol (moduł, funkcja, argument, właściwość, klasa, stała, typ, pakiet itp.), którego nazwa zawiera experimental lub Experimental ; Lub
    • dowolny symbol, którego pełna nazwa zawiera moduł, klasę lub pakiet, który sam w sobie jest eksperymentalny. Obejmuje to pola i podkomunikaty dowolnego bufora protokołu zwanego experimental .
  • Inne języki : API TensorFlow w językach innych niż Python i C, takich jak:

    i interfejsy API TensorFlow Lite w szczególności w językach innych niż Java/Kotlin, C, Objective-C i Swift

  • Szczegóły operacji złożonych: wiele funkcji publicznych w Pythonie rozszerza się do kilku prymitywnych operacji na grafie, a te szczegóły będą częścią wszelkich wykresów zapisanych na dysku jako GraphDef s. Szczegóły te mogą ulec zmianie w przypadku mniejszych wydań. W szczególności testy regresyjne sprawdzające dokładne dopasowanie wykresów prawdopodobnie nie sprawdzą się w przypadku mniejszych wersji, nawet jeśli zachowanie wykresu powinno pozostać niezmienione, a istniejące punkty kontrolne nadal będą działać.

  • Szczegóły liczbowe zmiennoprzecinkowe: określone wartości zmiennoprzecinkowe obliczone przez ops mogą ulec zmianie w dowolnym momencie. Użytkownicy powinni polegać wyłącznie na przybliżonej dokładności i stabilności numerycznej, a nie na konkretnych obliczonych bitach. Zmiany we wzorach numerycznych w wersjach mniejszych i poprawkowych powinny skutkować porównywalną lub lepszą dokładnością, z zastrzeżeniem, że w przypadku uczenia maszynowego zwiększona dokładność określonych formuł może skutkować zmniejszeniem dokładności całego systemu.

  • Liczby losowe: Konkretne obliczone liczby losowe mogą ulec zmianie w dowolnym momencie. Użytkownicy powinni polegać wyłącznie na przybliżonych prawidłowych rozkładach i sile statystycznej, a nie na konkretnych obliczonych bitach. Aby uzyskać szczegółowe informacje, zobacz przewodnik dotyczący generowania liczb losowych .

  • Odchylenie wersji w rozproszonym Tensorflow: Uruchamianie dwóch różnych wersji TensorFlow w jednym klastrze nie jest obsługiwane. Nie ma żadnych gwarancji co do wstecznej kompatybilności protokołu przewodowego.

  • Błędy: Zastrzegamy sobie prawo do wprowadzenia zmian w zachowaniu niezgodnym wstecz (choć nie w interfejsie API), jeśli bieżąca implementacja jest wyraźnie zepsuta, to znaczy, jeśli jest sprzeczna z dokumentacją lub jeśli dobrze znane i dobrze określone zamierzone zachowanie nie zostało prawidłowo wdrożone z powodu na błąd. Na przykład, jeśli optymalizator twierdzi, że implementuje dobrze znany algorytm optymalizacji, ale nie pasuje do tego algorytmu z powodu błędu, naprawimy optymalizator. Nasza poprawka może złamać kod, opierając się na niewłaściwym zachowaniu zbieżności. Takie zmiany odnotujemy w informacjach o wydaniu.

  • Nieużywany interfejs API: Zastrzegamy sobie prawo do wprowadzania niekompatybilnych wstecz zmian w interfejsach API, dla których nie znaleźliśmy udokumentowanego zastosowania (poprzez przeprowadzenie audytu wykorzystania TensorFlow za pomocą wyszukiwania w GitHub). Przed wprowadzeniem jakichkolwiek takich zmian ogłosimy nasz zamiar wprowadzenia zmiany na liście mailingowej ogłoszeniowej@ , podając instrukcje dotyczące sposobu usunięcia ewentualnych usterek (jeśli dotyczy) i poczekamy dwa tygodnie, aby dać naszej społeczności szansę podzielenia się swoją opinią .

  • Zachowanie błędne: Możemy zastąpić błędy zachowaniem niebędącym błędem. Na przykład możemy zmienić funkcję, aby obliczyć wynik, zamiast zgłaszać błąd, nawet jeśli błąd ten jest udokumentowany. Zastrzegamy sobie także prawo do zmiany treści komunikatów o błędach. Ponadto typ błędu może się zmienić, chyba że w dokumentacji określono typ wyjątku dla konkretnego warunku błędu.

Zgodność zapisanych modeli, wykresów i punktów kontrolnych

SavedModel to preferowany format serializacji do użycia w programach TensorFlow. SavedModels składają się z dwóch części: jednego lub większej liczby wykresów zakodowanych jako GraphDefs i punktu kontrolnego. Wykresy opisują przepływ danych do wykonania, a punkty kontrolne zawierają zapisane wartości tensora zmiennych na wykresie.

Wielu użytkowników TensorFlow tworzy SavedModels, a następnie ładuje je i wykonuje w późniejszej wersji TensorFlow. Zgodnie z semver , SavedModels napisane w jednej wersji TensorFlow można załadować i ocenić za pomocą nowszej wersji TensorFlow z tą samą wersją główną.

Udzielamy dodatkowych gwarancji na obsługiwane SavedModels. Nazywamy SavedModel, który został utworzony przy użyciu wyłącznie nieprzestarzałych, nieeksperymentalnych i niezgodnych interfejsów API w głównej wersji TensorFlow N SavedModel obsługiwany jest w wersji N Każdy SavedModel obsługiwany w głównej wersji TensorFlow N może zostać załadowany i wykonany za pomocą głównej wersji TensorFlow N+1 . Jednakże funkcjonalność wymagana do zbudowania lub modyfikacji takiego modelu może już nie być dostępna, dlatego ta gwarancja dotyczy wyłącznie niezmodyfikowanego SavedModel.

Dołożymy wszelkich starań, aby zachować kompatybilność wsteczną tak długo, jak to możliwe, aby serializowane pliki nadawały się do użytku przez długi czas.

Kompatybilność z GraphDefem

Wykresy są serializowane poprzez bufor protokołu GraphDef . Aby ułatwić wstecznie niekompatybilne zmiany na wykresach, każdy GraphDef ma numer wersji oddzielny od wersji TensorFlow. Na przykład GraphDef w wersji 17 wycofał opcję inv na rzecz reciprocal . Semantyka to:

  • Każda wersja TensorFlow obsługuje interwał wersji GraphDef . Odstęp ten będzie stały w przypadku wydań poprawek i będzie się zwiększał w przypadku mniejszych wydań. Porzucenie wsparcia dla wersji GraphDef będzie miało miejsce tylko w przypadku głównej wersji TensorFlow (i będzie zgodne tylko z obsługą wersji gwarantowaną dla SavedModels).

  • Nowo utworzonym wykresom przypisywany jest numer najnowszej wersji GraphDef .

  • Jeśli dana wersja TensorFlow obsługuje wersję wykresu GraphDef , będzie ładować i oceniać z takim samym zachowaniem, jak wersja TensorFlow użyta do jego wygenerowania (z wyjątkiem szczegółów liczbowych zmiennoprzecinkowych i liczb losowych, jak opisano powyżej), niezależnie od głównego wersja TensorFlow. W szczególności GraphDef, który jest kompatybilny z plikiem punktu kontrolnego w jednej wersji TensorFlow (tak jak ma to miejsce w przypadku SavedModel), pozostanie kompatybilny z tym punktem kontrolnym w kolejnych wersjach, o ile obsługiwany będzie GraphDef.

    Należy pamiętać, że dotyczy to tylko serializowanych wykresów w GraphDefs (i SavedModels): Kod odczytujący punkt kontrolny może nie być w stanie odczytać punktów kontrolnych wygenerowanych przez ten sam kod z inną wersją TensorFlow.

  • Jeśli górna granica GraphDef zostanie zwiększona do X w (pomniejszej) wersji, minie co najmniej sześć miesięcy, zanim dolna granica zostanie zwiększona do X. Na przykład (używamy tutaj hipotetycznych numerów wersji):

    • TensorFlow 1.2 może obsługiwać wersje GraphDef od 4 do 7.
    • TensorFlow 1.3 może dodać wersję GraphDef 8 i obsługiwać wersje od 4 do 8.
    • Co najmniej sześć miesięcy później TensorFlow 2.0.0 mógł zrezygnować ze wsparcia dla wersji 4 do 7, pozostawiając jedynie wersję 8.

    Należy pamiętać, że ponieważ główne wersje TensorFlow są zwykle publikowane w odstępie większym niż 6 miesięcy, gwarancje dla obsługiwanych SavedModels wyszczególnione powyżej są znacznie silniejsze niż 6-miesięczna gwarancja dla GraphDefs.

Wreszcie, gdy obsługa wersji GraphDef zostanie porzucona, spróbujemy zapewnić narzędzia do automatycznej konwersji wykresów do nowszej obsługiwanej wersji GraphDef .

Zgodność wykresów i punktów kontrolnych podczas rozszerzania TensorFlow

Ta sekcja jest istotna tylko w przypadku wprowadzania niezgodnych zmian w formacie GraphDef , na przykład podczas dodawania operacji, usuwania operacji lub zmiany funkcjonalności istniejących operacji. Poprzednia sekcja powinna wystarczyć większości użytkowników.

Kompatybilność wsteczna i częściowa do przodu

Nasz schemat wersjonowania ma trzy wymagania:

  • Kompatybilność wsteczna obsługująca ładowanie wykresów i punktów kontrolnych utworzonych za pomocą starszych wersji TensorFlow.
  • Kompatybilność w przód w celu obsługi scenariuszy, w których producent wykresu lub punktu kontrolnego jest aktualizowany do nowszej wersji TensorFlow przed konsumentem.
  • Włącz rozwijanie TensorFlow w niekompatybilny sposób. Na przykład usuwanie operacji, dodawanie atrybutów i usuwanie atrybutów.

Należy pamiętać, że chociaż mechanizm wersji GraphDef jest niezależny od wersji TensorFlow, zmiany w formacie GraphDef , które są wstecznie kompatybilne, są nadal ograniczone przez wersjonowanie semantyczne. Oznacza to, że funkcjonalność można usunąć lub zmienić tylko pomiędzy MAJOR wersjami TensorFlow (takimi jak 1.7 do 2.0 ). Dodatkowo w wydaniach poprawek (na przykład 1.x.1 do 1.x.2 ) egzekwowana jest kompatybilność w przód.

Aby zapewnić kompatybilność wstecz i w przód oraz wiedzieć, kiedy należy wymusić zmiany w formatach, wykresy i punkty kontrolne posiadają metadane opisujące czas ich utworzenia. W poniższych sekcjach szczegółowo opisano implementację TensorFlow i wytyczne dotyczące rozwijanych wersji GraphDef .

Niezależne schematy wersji danych

Istnieją różne wersje danych dla wykresów i punktów kontrolnych. Te dwa formaty danych ewoluują w różnym tempie od siebie nawzajem, a także z różną szybkością w porównaniu z TensorFlow. Obydwa systemy wersjonowania są zdefiniowane w core/public/version.h . Za każdym razem, gdy dodawana jest nowa wersja, w nagłówku dodawana jest notatka zawierająca szczegółowe informacje o zmianach i datę.

Dane, producenci i konsumenci

Rozróżniamy następujące rodzaje informacji o wersji danych:

  • producenci : pliki binarne generujące dane. Producenci mają wersję ( producer ) i minimalną wersję konsumencką, z którą są kompatybilni ( min_consumer ).
  • konsumenci : pliki binarne zużywające dane. Konsumenci mają wersję ( consumer ) i minimalną wersję producenta, z którą są kompatybilni ( min_producer ).

Każdy fragment wersjonowanych danych ma pole VersionDef versions , które rejestruje producer , który stworzył dane, min_consumer , z którym dane są kompatybilne, oraz listę wersji bad_consumers , które są niedozwolone.

Domyślnie, gdy producent tworzy pewne dane, dane dziedziczą wersję producer i wersję min_consumer . bad_consumers można ustawić, jeśli wiadomo, że określone wersje konsumenckie zawierają błędy i należy ich unikać. Konsument może zaakceptować dane, jeżeli spełnione są wszystkie poniższe warunki:

  • consumer >= min_consumer danych
  • producer danych >= min_producer konsumenta
  • consumer nie ma w danych bad_consumers

Ponieważ zarówno producenci, jak i konsumenci pochodzą z tej samej bazy kodu TensorFlow, core/public/version.h zawiera główną wersję danych, która jest traktowana jako producer lub consumer w zależności od kontekstu oraz zarówno min_consumer , jak i min_producer (potrzebne odpowiednio producentom i konsumentom) . Konkretnie,

  • W przypadku wersji GraphDef mamy TF_GRAPH_DEF_VERSION , TF_GRAPH_DEF_VERSION_MIN_CONSUMER i TF_GRAPH_DEF_VERSION_MIN_PRODUCER .
  • W przypadku wersji punktu kontrolnego mamy TF_CHECKPOINT_VERSION , TF_CHECKPOINT_VERSION_MIN_CONSUMER i TF_CHECKPOINT_VERSION_MIN_PRODUCER .

Dodaj nowy atrybut domyślny do istniejącej operacji

Postępowanie zgodnie z poniższymi wskazówkami zapewnia zgodność w przyszłości tylko wtedy, gdy zestaw operacji nie uległ zmianie:

  1. Jeśli wymagana jest kompatybilność w przód, ustaw strip_default_attrs na True podczas eksportowania modelu przy użyciu metod tf.saved_model.SavedModelBuilder.add_meta_graph_and_variables i tf.saved_model.SavedModelBuilder.add_meta_graph klasy SavedModelBuilder lub tf.estimator.Estimator.export_saved_model
  2. Spowoduje to usunięcie atrybutów o wartościach domyślnych w momencie produkcji/eksportu modeli. Dzięki temu wyeksportowany plik tf.MetaGraphDef nie będzie zawierał nowego atrybutu op, gdy zostanie użyta wartość domyślna.
  3. Posiadanie tej kontroli może pozwolić nieaktualnym klientom (na przykład obsługującym pliki binarne, które są opóźnione w stosunku do plików binarnych szkoleniowych) na dalsze ładowanie modeli i zapobieganie przerwom w udostępnianiu modeli.

Ewoluujące wersje GraphDef

W tej sekcji wyjaśniono, jak używać tego mechanizmu wersjonowania do wprowadzania różnych typów zmian w formacie GraphDef .

Dodaj op

Dodaj nową opcję jednocześnie do konsumentów i producentów i nie zmieniaj żadnych wersji GraphDef . Tego typu zmiany są automatycznie kompatybilne wstecz i nie mają wpływu na plan kompatybilności w przyszłości, ponieważ istniejące skrypty producentów nie będą nagle korzystać z nowej funkcjonalności.

Dodaj op i przełącz istniejące opakowania Pythona, aby z niego korzystać

  1. Wdróż nową funkcjonalność konsumencką i zwiększ wersję GraphDef .
  2. Jeśli możliwe jest, aby wrappery korzystały z nowej funkcjonalności tylko w przypadkach, które wcześniej nie działały, wrappery można teraz zaktualizować.
  3. Zmień opakowania języka Python, aby korzystać z nowej funkcjonalności. Nie zwiększaj min_consumer , ponieważ modele, które nie korzystają z tej opcji, nie powinny się psuć.

Usuń lub ogranicz funkcjonalność op

  1. Napraw wszystkie skrypty producenta (nie sam TensorFlow), aby nie korzystały z zablokowanej operacji lub funkcjonalności.
  2. Zwiększ wersję GraphDef i zaimplementuj nową funkcjonalność konsumencką, która blokuje usunięte operacje lub funkcje GraphDefs w nowej wersji i nowszych. Jeśli to możliwe, spraw, aby TensorFlow przestał produkować GraphDefs z zakazaną funkcjonalnością. Aby to zrobić, dodaj REGISTER_OP(...).Deprecated(deprecated_at_version, message) .
  3. Poczekaj na wydanie główne ze względu na kompatybilność wsteczną.
  4. Zwiększ min_producer do wersji GraphDef z (2) i całkowicie usuń tę funkcjonalność.

Zmień funkcjonalność operacji

  1. Dodaj nową podobną operację o nazwie SomethingV2 lub podobną i przejdź przez proces jej dodawania i przełączania istniejących opakowań Pythona, aby z niego korzystać. Aby zapewnić zgodność z przyszłymi wersjami, podczas zmiany opakowań Pythona użyj kontroli sugerowanych w compat.py .
  2. Usuń starą op (można to zrobić tylko w przypadku poważnej zmiany wersji ze względu na kompatybilność wsteczną).
  3. Zwiększ min_consumer , aby wykluczyć konsumentów ze starym op, dodaj ponownie stary op jako alias dla SomethingV2 i wykonaj proces, aby przełączyć istniejące opakowania Pythona, aby z niego korzystały.
  4. Przejdź przez proces, aby usunąć SomethingV2 .

Zablokuj pojedynczą niebezpieczną wersję konsumencką

  1. Podbij wersję GraphDef i dodaj złą wersję do bad_consumers dla wszystkich nowych GraphDef. Jeśli to możliwe, dodaj do bad_consumers tylko dla GraphDefs, które zawierają określoną operację lub coś podobnego.
  2. Jeśli obecni konsumenci mają złą wersję, wypchnij ją tak szybko, jak to możliwe.