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

Введение

В TensorFlow Hub, помимо других ресурсов, размещаются SavedModels для TensorFlow 2. Их можно загрузить обратно в программу Python с помощью obj = hub.load(url) [ подробнее ]. Возвращенный obj является результатом tf.saved_model.load() (см. руководство SavedModel TensorFlow). Этот объект может иметь произвольные атрибуты: 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 для вывода (например, развертывание SavedModel в TF Serving или TF Lite). Сигнатуры вывода недостаточно выразительны для поддержки тонкой настройки, а tf.function предоставляет более естественный и выразительный API Python для повторно используемой модели.

Связь с библиотеками построения моделей

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

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

Связь с «Общими API-интерфейсами SavedModel» для конкретных задач.

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

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

Атрибуты

Многоразовая сохраненная модель — это сохраненная модель 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.функций, каждая из которых принимает нулевые входные данные и возвращает один скалярный тензор с плавающей запятой. Для более точной настройки пользователю SavedModel рекомендуется включить их в качестве дополнительных условий регуляризации в потери (в простейшем случае без дальнейшего масштабирования). Обычно они используются для представления регуляризаторов веса. (Из-за отсутствия входных данных эти tf.functions не могут выражать регуляризаторы активности.)

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

Функция __call__

Восстановленный объект SavedModel имеет атрибут obj 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 определяет выходные типы и формы, а также их зависимость от входных данных.

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

Многоразовая сохраненная модель может предоставлять несколько частей модели описанным выше способом, помещая их в именованные подобъекты, например, 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.