Формат концентратора TF1

При запуске в 2018 году TensorFlow Hub предлагал один тип ресурсов: формат TF1 Hub для импорта в программы TensorFlow 1.

На этой странице объясняется, как использовать формат концентратора TF1 в TF1 (или режим совместимости с TF1 в TF2) с классом hub.Module и связанными API. (Обычно используется для построения tf.Graph , возможно внутри TF1 Estimator , путем объединения одной или нескольких моделей в формате TF1 Hub с tf.compat.layers или tf.layers ).

Пользователи TensorFlow 2 (вне режима совместимости с TF1) должны использовать новый API с hub.load() или hub.KerasLayer . Новый API загружает новый тип ресурсов TF2 SavedModel, но также имеет ограниченную поддержку загрузки формата TF1 Hub в TF2 .

Использование модели в формате TF1 Hub

Создание экземпляра модели в формате TF1 Hub

Модель в формате TF1 Hub импортируется в программу TensorFlow путем создания объекта hub.Module из строки с его URL-адресом или путем к файловой системе, например:

m = hub.Module("path/to/a/module_dir")

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

Кэширующие модули

При создании модуля из URL-адреса содержимое модуля загружается и кэшируется во временном каталоге локальной системы. Место, где кэшируются модули, можно переопределить с помощью переменной среды TFHUB_CACHE_DIR . Подробнее см. Кэширование .

Применение модуля

После создания модуль m может быть вызван ноль или более раз, как функция Python, от тензорных входных данных к тензорным выходным данным:

y = m(x)

Каждый такой вызов добавляет к текущему графу TensorFlow операции для вычисления y из x . Если это включает в себя переменные с обученными весами, они используются всеми приложениями.

Модули могут определять несколько именованных подписей , чтобы их можно было применять более чем одним способом (аналогично тому, как объекты Python имеют методы ). В документации модуля должны быть описаны доступные подписи. Приведенный выше вызов применяет подпись с именем "default" . Любую подпись можно выбрать, передав ее имя в необязательный аргумент signature= .

Если у подписи есть несколько входных данных, они должны быть переданы как словарь с ключами, определенными подписью. Аналогичным образом, если подпись имеет несколько выходных данных, их можно получить в виде словаря, передав as_dict=True под ключами, определенными в подписи (ключ "default" предназначен для одного возвращаемого вывода, если as_dict=False ). Таким образом, наиболее общая форма применения модуля выглядит так:

outputs = m(dict(apples=x1, oranges=x2), signature="fruit_to_pet", as_dict=True)
y1 = outputs["cats"]
y2 = outputs["dogs"]

Вызывающий должен предоставить все входные данные, определенные сигнатурой, но нет необходимости использовать все выходные данные модуля. TensorFlow будет запускать только те части модуля, которые становятся зависимостями цели в tf.Session.run() . Действительно, издатели модулей могут предоставлять различные выходные данные для расширенного использования (например, активацию промежуточных слоев) наряду с основными выходными данными. Потребители модулей должны корректно обрабатывать дополнительные выходные данные.

Пробуем альтернативные модули

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

С этой целью мы поддерживаем коллекцию рекомендуемых Common Signatures для популярных задач.

Создание нового модуля

Примечание о совместимости

Формат TF1 Hub ориентирован на TensorFlow 1. Он лишь частично поддерживается TF Hub в TensorFlow 2. Вместо этого рассмотрите возможность публикации в новом формате TF2 SavedModel .

Формат TF1 Hub подобен формату SavedModel TensorFlow 1 на синтаксическом уровне (те же имена файлов и протокольные сообщения), но семантически отличается, чтобы обеспечить повторное использование, компоновку и повторное обучение модулей (например, другое хранение инициализаторов ресурсов, разные теги). соглашения для метаграфов). Самый простой способ отличить их друг от друга на диске — это наличие или отсутствие файла tfhub_module.pb .

Общий подход

Чтобы определить новый модуль, издатель вызывает hub.create_module_spec() с функцией module_fn . Эта функция строит график, представляющий внутреннюю структуру модуля, используя tf.placeholder() для входных данных, которые должны быть предоставлены вызывающей стороной. Затем он определяет подписи, вызывая hub.add_signature(name, inputs, outputs) один или несколько раз.

Например:

def module_fn():
  inputs = tf.placeholder(dtype=tf.float32, shape=[None, 50])
  layer1 = tf.layers.dense(inputs, 200)
  layer2 = tf.layers.dense(layer1, 100)
  outputs = dict(default=layer2, hidden_activations=layer1)
  # Add default signature.
  hub.add_signature(inputs=inputs, outputs=outputs)

...
spec = hub.create_module_spec(module_fn)

Результат hub.create_module_spec() можно использовать вместо пути для создания экземпляра объекта модуля в конкретном графе TensorFlow. В таком случае контрольной точки нет, и вместо этого экземпляр модуля будет использовать инициализаторы переменных.

Любой экземпляр модуля можно сериализовать на диск с помощью его метода export(path, session) . Экспорт модуля сериализует его определение вместе с текущим состоянием его переменных в session в переданный путь. Это можно использовать при экспорте модуля в первый раз, а также при экспорте настроенного модуля.

Для совместимости с оценщиками hub.LatestModuleExporter экспортирует модули из последней контрольной точки точно так же, как tf.estimator.LatestExporter экспортирует всю модель из последней контрольной точки.

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

Реальный пример

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

Тонкая настройка

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

Для потребителей

Чтобы включить точную настройку, создайте экземпляр модуля с помощью hub.Module(..., trainable=True) , чтобы сделать его переменные обучаемыми, и импортируйте REGULARIZATION_LOSSES REGULARIZATION_LOSSES . Если модуль имеет несколько вариантов графика, обязательно выберите тот, который подходит для обучения. Обычно это тот, у которого есть теги {"train"} .

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

Для издателей

Чтобы упростить настройку для потребителей, помните о следующем:

  • Тонкая настройка требует регуляризации. Ваш модуль экспортируется с коллекцией REGULARIZATION_LOSSES , что превращает ваш выбор tf.layers.dense(..., kernel_regularizer=...) и т. д. в то, что потребитель получает от tf.losses.get_regularization_losses() . Предпочтите этот способ определения потерь регуляризации L1/L2.

  • В модели издателя избегайте определения регуляризации L1/L2 с помощью параметров l1_ и l2_regularization_strength tf.train.FtrlOptimizer , tf.train.ProximalGradientDescentOptimizer и других проксимальных оптимизаторов. Они не экспортируются вместе с модулем, и глобальная настройка силы регуляризации может быть неприемлемой для потребителя. За исключением регуляризации L1 в широких (т.е. разреженных линейных) или широких и глубоких моделях, должна быть возможность вместо этого использовать отдельные потери регуляризации.

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