Совместимость версий TensorFlow

Этот документ предназначен для пользователей, которым необходима обратная совместимость между различными версиями TensorFlow (как для кода, так и для данных), а также для разработчиков, которые хотят изменить TensorFlow, сохранив совместимость.

Семантическое версионирование 2.0

TensorFlow использует Semantic Versioning 2.0 ( semver ) для своего общедоступного API. Каждая версия выпуска TensorFlow имеет форму MAJOR.MINOR.PATCH . Например, версия TensorFlow 1.2.3 имеет MAJOR версию 1, MINOR версию 2 и PATCH версию 3. Изменения каждого числа имеют следующее значение:

  • ОСНОВНЫЕ : Потенциально обратно несовместимые изменения. Код и данные, которые работали с предыдущим основным выпуском, не обязательно будут работать с новым выпуском. Однако в некоторых случаях существующие графики и контрольные точки TensorFlow можно перенести в более новую версию; дополнительные сведения о совместимости данных см. в разделе «Совместимость графиков и контрольных точек» .

  • MINOR : функции обратной совместимости, повышение скорости и т. д. Код и данные, которые работали с предыдущим второстепенным выпуском и зависят только от неэкспериментального общедоступного API, продолжат работать без изменений. Подробную информацию о том, что является общедоступным API, а что нет, см. в разделе «Что покрывается» .

  • ИСПРАВЛЕНИЕ : исправлены ошибки обратной совместимости.

Например, в выпуске 1.0.0 представлены обратно несовместимые изменения по сравнению с выпуском 0.12.1. Однако версия 1.1.1 была обратно совместима с версией 1.0.0.

Что покрывается

Только общедоступные API TensorFlow обратно совместимы со второстепенными версиями и версиями исправлений. Публичные API состоят из

  • Все документированные функции и классы Python в модуле tensorflow и его подмодулях, за исключением

    • Частные символы: любая функция, класс и т. д., имя которых начинается с _
    • Экспериментальные символы и символы tf.contrib , подробности см . ниже .

    Обратите внимание, что код в каталогах examples/ tools/ недоступен через модуль Python tensorflow и, следовательно, на него не распространяется гарантия совместимости.

    Если символ доступен через модуль Python tensorflow или его подмодули, но не задокументирован, то он не считается частью общедоступного API.

  • API совместимости (в Python — модуль tf.compat ). В основных версиях мы можем выпускать утилиты и дополнительные конечные точки, чтобы помочь пользователям перейти на новую основную версию. Эти символы API устарели и не поддерживаются (т. е. мы не будем добавлять какие-либо функции и исправлять ошибки, кроме устранения уязвимостей), но на них распространяются наши гарантии совместимости.

  • API TensorFlow C:

  • Следующие файлы буфера протокола:

Отдельный номер версии для TensorFlow Lite.

В настоящее время TensorFlow Lite распространяется как часть TensorFlow. Однако мы оставляем за собой право вносить изменения в будущие выпуски API-интерфейсов TensorFlow Lite по графику, отличному от расписания других API-интерфейсов TensorFlow, или даже переместить TensorFlow Lite в отдельный дистрибутив исходного кода и/или отдельный репозиторий исходного кода, отличный от TensorFlow.

По этой причине мы используем другой номер версии для TensorFlow Lite ( TFLITE_VERSION_STRING в tensorflow/lite/version.h и TfLiteVersion() в tensorflow/lite/c/c_api.h ), чем для TensorFlow ( TF_VERSION_STRING в tensorflow/core/public/version.h и TF_Version() в tensorflow/c/c_api.h ). В настоящее время эти два номера версий имеют одинаковое значение. Но в будущем они могут разойтись; например, мы можем увеличить основной номер версии TensorFlow Lite, не увеличивая основной номер версии TensorFlow, или наоборот.

Поверхность API, на которую распространяется номер версии TensorFlow Lite, состоит из следующих общедоступных API:

Экспериментальные символы не рассматриваются; подробности см. ниже .

Отдельный номер версии для API-интерфейсов расширения TensorFlow Lite.

TensorFlow Lite предоставляет API C для расширения интерпретатора TensorFlow Lite с помощью «пользовательских операций», которые обеспечивают определяемые пользователем операции в графе, или «делегатов», которые позволяют делегировать вычисления для графа (или для подмножества графа) пользовательский бэкэнд. Эти API, которые мы вместе называем «API расширения TensorFlow Lite», требуют более тесных зависимостей от некоторых деталей реализации TensorFlow Lite.

Мы оставляем за собой право вносить изменения в эти API в будущем, включая изменения, не имеющие обратной совместимости, по графику, отличному от графика других API TensorFlow Lite. Поэтому мы используем другой номер версии для API-интерфейсов расширения TensorFlow Lite, чем номера версий для TensorFlow Lite или TensorFlow (которые были описаны в предыдущем разделе). Мы представляем несколько новых API в TensorFlow Lite версии 2.15, чтобы получить версию API расширения TensorFlow Lite ( TFLITE_EXTENSION_APIS_VERSION_STRING в tensorflow/lite/version.h и TfLiteExtensionApisVersion() в tensorflow/lite/c/c_api.h ). Номер версии API-интерфейсов расширения TensorFlow Lite в настоящее время такой же, как номер версии для TensorFlow и TensorFlow Lite. Но в будущем они могут разойтись; например, мы можем увеличить основной номер версии для API-интерфейсов расширения TensorFlow Lite, не увеличивая основной номер версии для TensorFlow Lite, или наоборот.

Поверхность API, на которую распространяется номер версии API расширения TensorFlow Lite, состоит из следующих общедоступных API:

Опять же, экспериментальные символы не рассматриваются; подробности см. ниже .

Что не покрывается

Некоторые части TensorFlow могут в любой момент измениться обратно несовместимым образом. К ним относятся:

  • Экспериментальные API . Чтобы облегчить разработку, мы освобождаем от гарантий совместимости некоторые символы API, явно помеченные как экспериментальные. В частности, никакие гарантии совместимости не распространяются на следующее:

    • любой символ в модуле tf.contrib или его подмодулях;
    • любой символ (модуль, функция, аргумент, свойство, класс, константа, тип, пакет и т. д.), имя которого содержит experimental или Experimental ; или
    • любой символ, полное имя которого включает модуль, класс или пакет, который сам по себе является экспериментальным. Сюда входят поля и подсообщения любого буфера протокола, называемого experimental .
  • Другие языки : API-интерфейсы TensorFlow на языках, отличных от Python и C, например:

    и API-интерфейсы TensorFlow Lite на языках, отличных от Java/Kotlin, C, Objective-C и Swift, в частности.

    • C++ (доступен через файлы заголовков в tensorflow/lite/ )
  • Подробности составных операций: многие общедоступные функции в Python расширяются до нескольких примитивных операций в графе, и эти детали будут частью любых графиков, сохраненных на диске как GraphDef s. Эти детали могут измениться для второстепенных выпусков. В частности, регрессионные тесты, проверяющие точное соответствие между графиками, скорее всего, не будут работать в второстепенных выпусках, хотя поведение графа должно оставаться неизменным, а существующие контрольные точки по-прежнему будут работать.

  • Подробности о числах с плавающей запятой: конкретные значения с плавающей запятой, вычисленные операторами, могут измениться в любое время. Пользователи должны полагаться только на приблизительную точность и числовую стабильность, а не на конкретные вычисленные биты. Изменения числовых формул в дополнительных выпусках и патчах должны привести к сопоставимой или повышенной точности, с оговоркой, что при машинном обучении повышение точности конкретных формул может привести к снижению точности для всей системы.

  • Случайные числа: конкретные вычисленные случайные числа могут измениться в любое время. Пользователи должны полагаться только на приблизительно правильные распределения и статистическую достоверность, а не на конкретные вычисленные биты. Подробности смотрите в руководстве по генерации случайных чисел .

  • Несовпадение версий в распределенном Tensorflow: запуск двух разных версий TensorFlow в одном кластере не поддерживается. Нет никаких гарантий относительно обратной совместимости проводного протокола.

  • Ошибки: мы оставляем за собой право вносить изменения в обратно несовместимое поведение (но не API), если текущая реализация явно нарушена, то есть если она противоречит документации или если известное и четко определенное предполагаемое поведение не реализовано должным образом из-за к ошибке. Например, если оптимизатор заявляет, что реализует известный алгоритм оптимизации, но не соответствует этому алгоритму из-за ошибки, мы исправим оптимизатор. Наше исправление может привести к поломке кода из-за неправильного поведения конвергенции. Мы отметим такие изменения в примечаниях к выпуску.

  • Неиспользуемый API: мы оставляем за собой право вносить обратно несовместимые изменения в API, для которых не обнаружено документированного использования (путем проведения аудита использования TensorFlow с помощью поиска на GitHub). Прежде чем вносить какие-либо такие изменения, мы объявим о своем намерении внести изменение в список рассылки анонса @ , предоставив инструкции по устранению любых неполадок (если применимо), и подождем две недели, чтобы дать нашему сообществу возможность поделиться своими отзывами. .

  • Поведение при ошибке: Мы можем заменить ошибки поведением, не являющимся ошибками. Например, мы можем изменить функцию для вычисления результата вместо того, чтобы выдавать ошибку, даже если эта ошибка задокументирована. Мы также оставляем за собой право изменять текст сообщений об ошибках. Кроме того, тип ошибки может измениться, если в документации не указан тип исключения для конкретного состояния ошибки.

Совместимость сохраненных моделей, графиков и контрольных точек.

SavedModel — это предпочтительный формат сериализации для использования в программах TensorFlow. SavedModels состоят из двух частей: один или несколько графиков, закодированных как GraphDefs , и контрольная точка. Графики описывают поток данных выполняемых операций, а контрольные точки содержат сохраненные тензорные значения переменных на графике.

Многие пользователи TensorFlow создают SavedModels, загружают и выполняют их с помощью более поздней версии TensorFlow. В соответствии с semver , SavedModels, написанные с использованием одной версии TensorFlow, могут быть загружены и оценены с помощью более поздней версии TensorFlow с той же основной версией.

Мы даем дополнительные гарантии на поддерживаемые SavedModels. Мы вызываем SavedModel, который был создан с использованием только неустаревших, неэкспериментальных и несовместимых API в основной версии N TensorFlow , SavedModel, поддерживаемый в версии N Любая SavedModel, поддерживаемая в основной версии N TensorFlow, может быть загружена и выполнена с основной версией TensorFlow N+1 . Однако функциональность, необходимая для создания или изменения такой модели, может быть больше недоступна, поэтому эта гарантия распространяется только на немодифицированную SavedModel.

Мы постараемся сохранить обратную совместимость как можно дольше, чтобы сериализованные файлы можно было использовать в течение длительного периода времени.

Совместимость с GraphDef

Графики сериализуются через буфер протокола GraphDef . Чтобы облегчить обратно несовместимые изменения в графах, каждый GraphDef имеет номер версии, отдельный от версии TensorFlow. Например, GraphDef версии 17 inv op отказался от reciprocal . Семантика такова:

  • Каждая версия TensorFlow поддерживает определенный интервал версий GraphDef . Этот интервал будет постоянным для всех выпусков исправлений и будет только увеличиваться для второстепенных выпусков. Отказ от поддержки версии GraphDef произойдет только для основной версии TensorFlow (и только в соответствии с поддержкой версии, гарантированной для SavedModels).

  • Вновь созданным графикам присваивается номер последней версии GraphDef .

  • Если данная версия TensorFlow поддерживает версию графика GraphDef , она будет загружаться и оцениваться с тем же поведением, что и версия TensorFlow, использованная для его создания (за исключением числовых данных с плавающей запятой и случайных чисел, как описано выше), независимо от основных версия TensorFlow. В частности, GraphDef, который совместим с файлом контрольной точки в одной версии TensorFlow (например, в SavedModel), останется совместимым с этой контрольной точкой в ​​последующих версиях, пока поддерживается GraphDef.

    Обратите внимание, что это относится только к сериализованным графам в GraphDefs (и SavedModels): код , считывающий контрольную точку, может не иметь возможности читать контрольные точки, сгенерированные тем же кодом, использующим другую версию TensorFlow.

  • Если верхняя граница GraphDef увеличена до X в (второстепенной) версии, пройдет не менее шести месяцев, прежде чем нижняя граница будет увеличена до X. Например (здесь мы используем гипотетические номера версий):

    • TensorFlow 1.2 может поддерживать версии GraphDef с 4 по 7.
    • TensorFlow 1.3 может добавить GraphDef версии 8 и поддерживать версии с 4 по 8.
    • По крайней мере, шесть месяцев спустя TensorFlow 2.0.0 может отказаться от поддержки версий с 4 по 7, оставив только версию 8.

    Обратите внимание: поскольку основные версии TensorFlow обычно публикуются с интервалом более 6 месяцев, гарантии для поддерживаемых SavedModels, описанные выше, намного надежнее, чем 6-месячная гарантия для GraphDefs.

Наконец, когда поддержка версии GraphDef будет прекращена, мы попытаемся предоставить инструменты для автоматического преобразования графиков в более новую поддерживаемую версию GraphDef .

Совместимость графов и контрольных точек при расширении TensorFlow

Этот раздел актуален только при внесении несовместимых изменений в формат GraphDef , например при добавлении операций, удалении операций или изменении функциональности существующих операций. Предыдущего раздела должно быть достаточно для большинства пользователей.

Обратная и частичная прямая совместимость

Наша схема управления версиями имеет три требования:

  • Обратная совместимость для поддержки графиков загрузки и контрольных точек, созданных с помощью более старых версий TensorFlow.
  • Прямая совместимость для поддержки сценариев, в которых производитель графа или контрольной точки обновляется до более новой версии TensorFlow раньше потребителя.
  • Включите развитие TensorFlow несовместимыми способами. Например, удаление операций, добавление атрибутов и удаление атрибутов.

Обратите внимание: хотя механизм версий GraphDef отделен от версии TensorFlow, обратно несовместимые изменения формата GraphDef по-прежнему ограничиваются семантическим управлением версиями. Это означает, что функциональность может быть удалена или изменена только между MAJOR версиями TensorFlow (например, с 1.7 по 2.0 ). Кроме того, в выпусках исправлений обеспечивается прямая совместимость (например, с 1.x.1 по 1.x.2 ).

Чтобы обеспечить обратную и прямую совместимость и знать, когда следует применять изменения в форматах, графики и контрольные точки имеют метаданные, описывающие, когда они были созданы. В разделах ниже подробно описана реализация TensorFlow и рекомендации по развитию версий GraphDef .

Независимые схемы версий данных

Существуют разные версии данных для графиков и контрольных точек. Эти два формата данных развиваются с разной скоростью друг от друга, а также с разной скоростью от TensorFlow. Обе системы управления версиями определены в core/public/version.h . При каждом добавлении новой версии в заголовок добавляется примечание с подробным описанием изменений и датой.

Данные, производители и потребители

Мы различаем следующие виды информации о версии данных:

  • производители : двоичные файлы, которые производят данные. У производителей есть версия ( producer ) и минимальная потребительская версия, с которой они совместимы ( min_consumer ).
  • Consumers : двоичные файлы, которые потребляют данные. У потребителей есть версия ( consumer ) и минимальная версия производителя, с которой они совместимы ( min_producer ).

Каждая часть версионных данных имеет поле VersionDef versions , в котором записан producer , создавший данные, min_consumer , с которым они совместимы, и список запрещенных версий bad_consumers .

По умолчанию, когда производитель создает некоторые данные, данные наследуют версии producer и min_consumer производителя. bad_consumers можно установить, если известно, что определенные потребительские версии содержат ошибки и их следует избегать. Потребитель может принять часть данных, если выполняются все следующие условия:

  • consumer >= min_consumer данных
  • producer данных >= min_producer потребителя
  • consumer не входит в данные bad_consumers

Поскольку и производители, и потребители происходят из одной и той же базы кода TensorFlow, core/public/version.h содержит версию основных данных, которая рассматривается как producer или consumer в зависимости от контекста, а также как min_consumer и min_producer (необходимы производителям и потребителям соответственно). . Конкретно,

  • Для версий GraphDef у нас есть TF_GRAPH_DEF_VERSION , TF_GRAPH_DEF_VERSION_MIN_CONSUMER и TF_GRAPH_DEF_VERSION_MIN_PRODUCER .
  • Для версий контрольных точек у нас есть TF_CHECKPOINT_VERSION , TF_CHECKPOINT_VERSION_MIN_CONSUMER и TF_CHECKPOINT_VERSION_MIN_PRODUCER .

Добавьте новый атрибут по умолчанию к существующей операции

Следование приведенным ниже инструкциям обеспечит прямую совместимость только в том случае, если набор операций не изменился:

  1. Если требуется прямая совместимость, установите для strip_default_attrs значение True при экспорте модели с помощью методов tf.saved_model.SavedModelBuilder.add_meta_graph_and_variables и tf.saved_model.SavedModelBuilder.add_meta_graph класса SavedModelBuilder или tf.estimator.Estimator.export_saved_model
  2. При этом удаляются атрибуты со значениями по умолчанию во время создания/экспорта моделей. Это гарантирует, что экспортированный tf.MetaGraphDef не будет содержать новый атрибут op при использовании значения по умолчанию.
  3. Наличие этого элемента управления может позволить устаревшим потребителям (например, обслуживающим двоичные файлы, которые отстают от обучающих двоичных файлов) продолжать загрузку моделей и предотвращать перебои в обслуживании моделей.

Развитие версий GraphDef

В этом разделе объясняется, как использовать этот механизм управления версиями для внесения различных типов изменений в формат GraphDef .

Добавить операцию

Добавьте новую операцию как для потребителей, так и для производителей одновременно и не изменяйте версии GraphDef . Изменения такого типа автоматически обеспечивают обратную совместимость и не влияют на план прямой совместимости, поскольку существующие сценарии производителей не будут внезапно использовать новые функции.

Добавьте операцию и переключите существующие оболочки Python, чтобы использовать ее.

  1. Внедрите новые потребительские функции и увеличьте версию GraphDef .
  2. Если можно заставить обертки использовать новый функционал только в тех случаях, которые раньше не работали, то обёртки можно обновить уже сейчас.
  3. Измените оболочки Python, чтобы использовать новую функциональность. Не увеличивайте min_consumer , поскольку модели, которые не используют эту операцию, не должны сломаться.

Удалить или ограничить функциональность оператора

  1. Исправьте все сценарии производителя (не сам TensorFlow), чтобы они не использовали запрещенную операцию или функциональность.
  2. Увеличьте версию GraphDef и реализуйте новую пользовательскую функциональность, которая запрещает удаленную операцию или функциональность GraphDefs в новой версии и выше. Если возможно, запретите TensorFlow создавать GraphDefs с запрещенной функциональностью. Для этого добавьте REGISTER_OP(...).Deprecated(deprecated_at_version, message) .
  3. Подождите основного выпуска в целях обратной совместимости.
  4. Увеличьте min_producer до версии GraphDef из (2) и полностью удалите эту функциональность.

Изменение функциональности оператора

  1. Добавьте новую аналогичную операцию с именем SomethingV2 или аналогичную и выполните процесс ее добавления и переключения существующих оболочек Python для ее использования. Чтобы обеспечить прямую совместимость, используйте проверки, предложенные в compat.py , при изменении оболочек Python.
  2. Удалите старую операцию (может произойти только при изменении основной версии из-за обратной совместимости).
  3. Увеличьте min_consumer чтобы исключить потребителей со старой операцией, добавьте старую операцию обратно в качестве псевдонима для SomethingV2 и пройдите процесс переключения существующих оболочек Python для ее использования.
  4. Пройдите процесс удаления SomethingV2 .

Запретить одну небезопасную потребительскую версию

  1. Улучшите версию GraphDef и добавьте плохую версию в bad_consumers для всех новых GraphDef. Если возможно, добавляйте в bad_consumers только те GraphDefs, которые содержат определенную операцию или что-то подобное.
  2. Если у существующих потребителей есть плохая версия, выбросьте их как можно скорее.