Перенос использования tf.summary на TF 2.x

Посмотреть на TensorFlow.org Запускаем в Google Colab Посмотреть исходный код на GitHub Скачать блокнот
import tensorflow as tf

TensorFlow 2.x включает в себя значительные изменения в tf.summary API , используемый для записи данных кратких для визуализации в TensorBoard.

Что изменилось

Это полезно думать о tf.summary API как два суб-API:

  • Набор опс для записи отдельных резюме - summary.scalar() , summary.histogram() , summary.image() , summary.audio() , и summary.text() - которые называются рядным из вашего кода модели.
  • Написание логики, которая собирает эти отдельные сводки и записывает их в специально отформатированный файл журнала (который затем TensorBoard считывает для создания визуализаций).

В TF 1.x

Две половинки должны были быть вручную соединены вместе - путем выборки сводной оп выходами через Session.run() и вызов FileWriter.add_summary(output, step) . v1.summary.merge_all() оп сделало это проще с помощью коллекции графа агрегировать все опы Резюме результатов, но этот подход все еще работает плохо для нетерпеливого исполнения и потока управления, что делает его особенно плохо подходит для 2.x. TF

В TF 2.X

Обе половины тесно интегрированы, и теперь отдельные tf.summary ОПС писать свои данные сразу при выполнении. Использование API из кода вашей модели все еще должно выглядеть знакомо, но теперь он удобен для активного выполнения, оставаясь совместимым с графическим режимом. Интегрируя обе половины средств API summary.FileWriter теперь является частью контекста выполнения TensorFlow и получает доступ непосредственно tf.summary опса, поэтому настройка писателей является основной частью , которая выглядит по- другому.

Пример использования с нетерпеливым исполнением, по умолчанию в TF 2.x:

writer = tf.summary.create_file_writer("/tmp/mylogs/eager")

with writer.as_default():
  for step in range(100):
    # other model code would go here
    tf.summary.scalar("my_metric", 0.5, step=step)
    writer.flush()
ls /tmp/mylogs/eager
events.out.tfevents.1633086727.kokoro-gcp-ubuntu-prod-1386032077.31590.0.v2

Пример использования с выполнением графа tf.function:

writer = tf.summary.create_file_writer("/tmp/mylogs/tf_function")

@tf.function
def my_func(step):
  with writer.as_default():
    # other model code would go here
    tf.summary.scalar("my_metric", 0.5, step=step)

for step in tf.range(100, dtype=tf.int64):
  my_func(step)
  writer.flush()
ls /tmp/mylogs/tf_function
events.out.tfevents.1633086728.kokoro-gcp-ubuntu-prod-1386032077.31590.1.v2

Пример использования с выполнением устаревшего графа TF 1.x:

g = tf.compat.v1.Graph()
with g.as_default():
  step = tf.Variable(0, dtype=tf.int64)
  step_update = step.assign_add(1)
  writer = tf.summary.create_file_writer("/tmp/mylogs/session")
  with writer.as_default():
    tf.summary.scalar("my_metric", 0.5, step=step)
  all_summary_ops = tf.compat.v1.summary.all_v2_summary_ops()
  writer_flush = writer.flush()


with tf.compat.v1.Session(graph=g) as sess:
  sess.run([writer.init(), step.initializer])

  for i in range(100):
    sess.run(all_summary_ops)
    sess.run(step_update)
    sess.run(writer_flush)
ls /tmp/mylogs/session
events.out.tfevents.1633086728.kokoro-gcp-ubuntu-prod-1386032077.31590.2.v2

Преобразование вашего кода

Преобразование существующего tf.summary использования в 2.x TF API не может быть надежно автоматизирован, поэтому tf_upgrade_v2 скрипт просто переписывает все это tf.compat.v1.summary . Для перехода на TF 2.x вам необходимо адаптировать код следующим образом:

  1. Набор писателя по умолчанию с помощью .as_default() должен присутствовать , чтобы использовать сводный опс

    • Это означает активное выполнение операций или использование операций при построении графа.
    • Без средства записи по умолчанию сводные операции становятся беззвучными.
    • По умолчанию писателей не (пока) распространяются через @tf.function границы выполнения - они обнаруживаются только тогда , когда функция прослеживается - так что лучше практика называть writer.as_default() внутри тела функции, а также для того, чтобы объект писателя продолжает существовать до тех пор , как @tf.function используется
  2. Значение «шаг» должно быть передано в каждый оп через step аргумент

    • TensorBoard требует значение шага для рендеринга данных в виде временного ряда.
    • Явная передача необходима, потому что глобальный шаг из TF 1.x был удален, поэтому каждая операция должна знать желаемую переменную шага для чтения
    • Для снижения шаблонного, экспериментальная поддержка регистрации значения шага по умолчанию доступна как tf.summary.experimental.set_step() , но это предварительная функциональность , которая может быть изменена без предварительного уведомления
  3. Сигнатуры функций отдельных сводных операций изменены

    • Возвращаемое значение теперь является логическим (указывает, действительно ли было написано резюме)
    • Второе имя параметра (если используется) изменился с tensor к data
    • collections параметр был удален; коллекции только TF 1.x
    • family параметр был удален; просто использовать tf.name_scope()
  4. [Только для устаревшего режима графа / пользователей, выполняющих сеанс]

    • Во- первых инициализацию писатель с v1.Session.run(writer.init())

    • Используйте v1.summary.all_v2_summary_ops() , чтобы получить все сводные 2.x TF опа для текущего графика, например , чтобы выполнить их с помощью Session.run()

    • Промойте писатель с v1.Session.run(writer.flush()) , а также для close()

Если TF код 1.x был используя вместо tf.contrib.summary API, это гораздо больше похоже на 2.x TF API, поэтому tf_upgrade_v2 скрипт позволит автоматизировать большинство этапов миграции (и испускают предупреждения или ошибки для любого использования , которые не могут быть полностью перенесенным). По большей части он просто переписывает API вызовы к tf.compat.v2.summary ; если вам нужно только совместимость с 2.x TF вы можете уронить compat.v2 и просто ссылаться на него , как tf.summary .

Дополнительные советы

Помимо вышеперечисленных критических областей, изменились и некоторые вспомогательные аспекты:

  • Условная запись (например, «журнал каждые 100 шагов») получила новый вид.

    • Для управления операциями и связанными с ними кода, завернуть их в правильной , если заявление (которое работает в нетерпеливом режиме и в @tf.function через автографа ) или tf.cond
    • Для того, чтобы контролировать только их резюме, используйте новый tf.summary.record_if() менеджера контекста, и передать его логическое состояние вашего выбора
    • Они заменяют шаблон TF 1.x:

      if condition:
        writer.add_summary()
      
  • Нет прямого написания tf.compat.v1.Graph - вместо использования трассировки функции

    • Выполнение графика в 2.x TF использования @tf.function вместо явного Graph
    • В 2.x ТФА использовать API , новая трассировку стиле tf.summary.trace_on() и tf.summary.trace_export() для записи выполняемых функций графики
  • Не более глобального кэширования писателей в LogDir с tf.summary.FileWriterCache

    • Пользователи должны либо реализовать свое собственное кэширование / обмен объектов писателя, или просто используйте отдельные автор (поддержку TensorBoard последним является в процессе )
  • Изменилось двоичное представление файла событий.

    • TensorBoard 1.x уже поддерживает новый формат; это различие влияет только на пользователей, которые вручную анализируют сводные данные из файлов событий.
    • Сводные данные теперь хранятся в виде тензорных байтов; Вы можете использовать tf.make_ndarray(event.summary.value[0].tensor) , чтобы преобразовать его в NumPy