Благодарим за настройку Google I/O. Посмотреть все сеансы по запросу Смотреть по запросу

Многоразовые сохраненные модели

Введение

TensorFlow Hub размещает SavedModels для TensorFlow 2, среди прочего. Их можно загрузить обратно в программу Python с помощью obj = hub.load(url) [ узнать больше ]. Возвращенный obj является результатом tf.saved_model.load() (см. руководство TensorFlow по SavedModel ). Этот объект может иметь произвольные атрибуты, такие как tf.functions, tf.Variables (инициализированные их предварительно обученными значениями), другие ресурсы и, рекурсивно, другие такие объекты.

На этой странице описывается интерфейс, который должен быть реализован загруженным obj для повторного использования в программе TensorFlow Python. SavedModels, соответствующие этому интерфейсу, называются Reusable SavedModels .

Повторное использование означает создание более крупной модели вокруг obj , включая возможность ее тонкой настройки. Тонкая настройка означает дальнейшее обучение веса загруженного obj как части окружающей модели. Функция потерь и оптимизатор определяются окружающей моделью; obj определяет только сопоставление входных и выходных активаций («прямой проход»), возможно, включая такие методы, как отсев или пакетная нормализация.

Команда TensorFlow Hub рекомендует реализовать интерфейс Reusable SavedModel во всех SavedModel, которые предназначены для повторного использования в указанном выше смысле. Многие утилиты из библиотеки tensorflow_hub , в частности hub.KerasLayer , для реализации требуют SavedModels.

Отношение к SignatureDefs

Этот интерфейс с точки зрения tf.functions и других функций TF2 отделен от сигнатур SavedModel, которые были доступны после TF1 и продолжают использоваться в TF2 для вывода (например, развертывание SavedModels в TF Serving или TF Lite). Сигнатуры для вывода недостаточно выразительны для поддержки тонкой настройки, а tf.function предоставляет более естественный и выразительный API Python для повторно используемой модели.

Отношение к библиотекам построения моделей

Reusable SavedModel использует только примитивы TensorFlow 2, не зависящие от какой-либо конкретной библиотеки для построения моделей, такой как Keras или Sonnet. Это облегчает повторное использование библиотек для построения моделей без зависимостей от исходного кода построения моделей.

Потребуется некоторая адаптация, чтобы загрузить Reusable SavedModels или сохранить их из любой заданной библиотеки построения моделей. Для Keras hub.KerasLayer обеспечивает загрузку, а встроенное сохранение Keras в формате SavedModel было переработано для TF2 с целью предоставления расширенного набора этого интерфейса (см. RFC от мая 2019 г.).

Отношение к конкретным задачам «Общие API SavedModel»

Определение интерфейса на этой странице допускает любое количество и тип входов и выходов. Общие API-интерфейсы SavedModel для TF Hub уточняют этот общий интерфейс с помощью соглашений об использовании для конкретных задач, чтобы сделать модели легко взаимозаменяемыми.

Определение интерфейса

Атрибуты

Многоразовая SavedModel — это SavedModel TensorFlow 2, такая что obj = tf.saved_model.load(...) возвращает объект со следующими атрибутами.

  • __call__ . Необходимый. Функция tf.function, реализующая расчет модели («прямой проход») в соответствии с приведенной ниже спецификацией.

  • variables : список объектов tf.Variable, в котором перечислены все переменные, используемые любым возможным вызовом __call__ , включая как обучаемые, так и необучаемые.

    Этот список можно опустить, если он пуст.

  • trainable_variables : список объектов tf.Variable, таких, что v.trainable истинно для всех элементов. Эти переменные должны быть подмножеством variables . Это переменные, которые необходимо обучать при тонкой настройке объекта. Создатель SavedModel может опустить здесь некоторые переменные, которые изначально были доступны для обучения, чтобы указать, что их не следует изменять во время тонкой настройки.

    Этот список можно не указывать, если он пуст, в частности, если SavedModel не поддерживает тонкую настройку.

  • regularization_losses : список tf.functions, каждая из которых принимает нулевые входные данные и возвращает один скалярный тензор с плавающей запятой. Для тонкой настройки пользователю SavedModel рекомендуется включить их в качестве дополнительных условий регуляризации в потери (в простейшем случае без дальнейшего масштабирования). Обычно они используются для представления регуляризаторов веса. (Из-за отсутствия входных данных эти tf.functions не могут выражать регуляризаторы активности.)

    Этот список можно не указывать, если он пустой, в частности, если SavedModel не поддерживает тонкую настройку или не желает прописывать регуляризацию веса.

Функция __call__

Восстановленный obj SavedModel имеет атрибут obj.__call__ , который является восстановленной функцией tf.function и позволяет вызывать obj следующим образом.

Синопсис (псевдокод):

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

Аргументы

Аргументы следующие.

  • Есть один позиционный обязательный аргумент с пакетом входных активаций SavedModel. Его тип является одним из

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

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

  • Может быть необязательное training аргумента ключевого слова, которое принимает логическое значение Python, True или False . Значение по умолчанию — False . Если модель поддерживает точную настройку, и если ее вычисления различаются между ними (например, как при исключении и пакетной нормализации), это различие реализуется с помощью этого аргумента. В противном случае этот аргумент может отсутствовать.

    Не требуется, чтобы __call__ принимал training аргумент с тензорным значением. Вызывающий должен использовать tf.cond() , если это необходимо для диспетчеризации между ними.

  • Создатель SavedModel может принять дополнительные необязательные kwargs с определенными именами.

    • Для аргументов с тензорным значением создатель SavedModel определяет их допустимые типы и формы. tf.function принимает значение Python по умолчанию для аргумента, который трассируется с помощью ввода tf.TensorSpec. Такие аргументы можно использовать для настройки числовых гиперпараметров, участвующих в __call__ (например, коэффициент отсева).

    • Для аргументов со значением Python создатель SavedModel определяет их допустимые значения. Такие аргументы можно использовать в качестве флагов для дискретного выбора в трассируемой функции (но не забывайте о комбинаторном взрыве трассировок).

Восстановленная функция __call__ должна предоставлять трассировки для всех допустимых комбинаций аргументов. Переключение training между True и False не должно изменять допустимость аргументов.

Результат

outputs от вызова obj могут быть

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

(В будущих версиях этого интерфейса могут быть разрешены более общие гнезда.) Тип возвращаемого значения может варьироваться в зависимости от значения kwargs в Python. Это позволяет флагам производить дополнительные выходные данные. Создатель SavedModel определяет выходные типы и формы и их зависимость от входных данных.

Именованные вызываемые объекты

Reusable SavedModel может предоставить несколько частей модели описанным выше способом, поместив их в именованные подобъекты, например, obj.foo , obj.bar и т. д. Каждый подобъект предоставляет метод __call__ и вспомогательные атрибуты переменных и т. д., характерные для этой части модели. В приведенном выше примере это будут obj.foo.__call__ , obj.foo.variables и так далее.

Обратите внимание, что этот интерфейс не охватывает подход добавления голой tf.function непосредственно как tf.foo .

Ожидается, что пользователи многоразовых сохраненных моделей будут обрабатывать только один уровень вложенности ( obj.bar но не obj.bar.baz ). (В будущих версиях этого интерфейса может быть разрешена более глубокая вложенность и может быть отменено требование, чтобы объект верхнего уровня был вызываемым сам по себе.)

Заключительные замечания

Отношение к внутрипроцессным API

В этом документе описывается интерфейс класса Python, который состоит из примитивов, таких как tf.function и tf.Variable, которые выдерживают циклическое обращение через сериализацию через tf.saved_model.save() и tf.saved_model.load() . Однако интерфейс уже присутствовал в исходном объекте, который был передан в tf.saved_model.save() . Адаптация к этому интерфейсу позволяет обмениваться частями модели через API-интерфейсы построения моделей в рамках одной программы TensorFlow.