Назад
249

Tensorboard для Pytorch

249

Введение

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

TensorBoard — инструмент для визуализации и мониторинга машинного обучения, разработанный Google в рамках проекта TensorFlow.

Среди его преимуществ в сравнении с аналогами (W&B, ClearML) выделяются:

  1. Простота настройки. Добавить логирование метрик можно за пару строчек кода, а для запуска сервера не нужно ничего настраивать.
  2. Поддержка многих форматов данных. К ним относятся скаляры, распределения, графы, картинки, аудио, видео, графики и многое другое.
  3. Бесплатное self-hosted решение. С ним вы будете уверены, что у вас всегда есть доступ к результатам ваших экспериментов.

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

  1. Медленная работа. Если количество запусков перевалит за сотню — Tensorboard начнёт подтормаживать.
  2. Отсутствие сложной группировки данных. Если у вас несколько разных экспериментов — будет крайне неудобно использовать Tensorboard.

В этой статье мы узнаем, как применять Tensorboard для логирования данных в Pytorch. Давайте разбираться со всем по порядку 🙂

Первичная настройка

Единой точкой входа является объект SummaryWriter, который и даёт нам возможность логировать. Его желательно закрывать в самом конце.

from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter()
#Some code
writer.close()

У SummaryWriter также есть несколько важных аргументов:

Название параметраОписаниеЗначение по умолчанию
log_dirПапка с логамиПапка в директории runs, название которой содержит дату. Например, runs/Aug02_19-01-07
max_queueМаксимальный размер очереди логируемых событий, при превышении которого принудительно произойдет запись на диск10
flush_secsЧастота записи логов на диск120

Для просмотра того, что было залогировано, нам нужно запустить сам Tensorboard: tensorboard --logdir directory_name.

Дополнительные параметры представлены в таблице:

Название параметраОписание
hostЗадаёт сетевой интерфейс, где запускается сервер Tensorboard. По умолчанию это localhost. Для доступа с помощью других устройств в сети можно указать 0.0.0.0, чтобы подключиться с любого IP-адреса.
portУказывает номер порта, где запускается сервер Tensorboard. По умолчанию это порт 6006.
window_titleПозволяет задавать заголовок окна браузера, где открыт Tensorboard. Очень удобно при просмотре разных его экземпляров.
samples_per_pluginПомогает ограничивать количество образцов (samples), которые отображаются каждым плагином в Tensorboard. По умолчанию это 10 для изображений, 500 для гистограмм и 1000 для скаляров. Если образцов больше — они даунсэмлятся до нужных лимитов. Например, при добавлении следующего аргумента мы повышаем количество отображаемых изображений до 1000:--samples_per_plugin=images=1000.

Логирование скаляров

Чаще всего нам нужно логировать скалярные значения: метрики, лосс, размер learning rate и другое. Для этого у SummaryWriter есть метод add_scalar.

writer.add_scalar(scalar_value=loss,
                  tag="train_loss",
                  global_step=step,
                  double_precision=False)

Первый аргумент здесь — значение скаляра. Второй — название. Третий — номер шага (отображается на графике на оси x). Последний — сохранение значения double вместо float.

Теперь если мы залогируем, например, тренировочный лосс и откроем Tensorboard, то увидим примерно следующее:

Рисунок 1. График тренировочного лосса

А если наведём на любую точку графика — увидим в ней значения X и Y.

Рисунок 2. График с проаннотированными значениями

Для лучшего отображения значений есть несколько полезных фичей. Во-первых, график можно привести к логарифмической шкале с помощью специальной кнопки:

Рисунок 3. График с логарифмированной шкалой Y

Во-вторых, данные можно сгладить через Smoothing. Он применит на них Exponential Moving Average (подробнее об этом мы рассказывали в нашей статье).

Рисунок 4. График с использованием Smoothing = 0.99

В левом углу есть возможность изменить ось X с помощью трёх вариантов:

  • STEP — шаг, то есть global_step;
  • RELATIVE — время от начала эксперимента;
  • WALL — абсолютное время.

Конечно, мы можем посмотреть несколько запусков, если выберем их одновременно.

Рисунок 5. Сравнение нескольких метрик

Скаляры можно объединить в группы. Например, если мы передадим в tag значение losses/train_loss — у нас появится группа losses со скаляром train_loss. Такая группировка очень удобна для отображения, поскольку скаляры находятся рядом.

Рисунок 6. Отображение группы скаляров

Иногда мы хотим отображать на одном графике несколько скаляров из одного запуска. Для этого нам нужно использовать add_custom_scalars. Его можно вызвать разово, и он имеет всего один аргумент layout. Это словарь, который позволяет объединять скаляры в один график. Давайте рассмотрим его на примере.

Предположим, мы хотим создать два графика: один для отображения значения функции потерь и «потолка» лосса (например, если мы знаем, что он не может быть больше какого-то числа). Второй — для отображения не просто значения лосса, но и его стандартного отклонения.

В таком случае передаём как аргумент:

layout = {'metrics': {'loss_epoch': ['Multiline', ['train_loss', 'train_loss_max']],
             'loss_epoch_margin': ['Margin', ['train_loss', 'margin_up', 'margin_down']],
             }
 }

Здесь мы объединяем скаляры train_loss и train_loss_max в график loss_epoch группы metrics с помощью метода Multiline, с одной стороны, и скаляры train_loss, margin_up и margin_down в график loss_epoch_margin той же группы через метод Margin.

Multiline — простое отображение нескольких скаляров на графике.

Margin — отображение трёх скаляров на графике.

Наибольшее и наименьшее значения обозначаются как границы, а оставшееся значение — как обычный график. При его использовании изменение параметра Smoothing ни на что не повлияет.

Для просмотра этих графиков нужно перейти во вкладку Custom Scalars.

Рисунок 7. Отображение Custom Scalars

Логирование распределений

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

writer.add_histogram(tag="probs_distribution_class_0",
                     values=output[:, 0],
                     global_step=idx)

Дополнительно возможно настроить способ деления данных на корзинки. За это отвечают аргументы bins (метод, аналогичный numpy.histogram) и max_bins (максимальное число корзинок).

При переходе в Tensorboard можно посмотреть графики в разделах distributions и histograms.

Для распределений, близких к нормальному, удобнее пользоваться distributions. Тогда на оси x изобразится global_step, а яркостью цвета обозначится плотность вероятности (чем светлее цвет, тем меньше вероятность увидеть значение).

Рисунок 8. Отображение графика во вкладке distributions

Для распределений, отличных от нормального, лучше применять histograms (хотя для близких к нормальному распределений эта вкладка тоже подходит). Здесь они представлены трёхмерно. На одной из осей отображается global_step, на другой — корзинки. Высота — количество значений.

Рисунок 9. Отображение графика во вкладке histograms

Логирование артефактов

В Tensorboard также можно логировать различные артефакты.

Граф вычислений

Если добавить в свой код следующие строчки кода — на вкладке graphs появится граф вычислений:

writer.add_graph(model=model, input_to_model=input_data)

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

Предположим, мы решили визуализировать resnet18. Тогда мы имеем:

Рисунок 10. Отображение графа (на стрелочках есть shape данных)

Если мы кликнем два раза на один из блоков — он развернётся:

Рисунок 11. Отображение графа с развёрнутым блоком

К сожалению, иногда части графа накладываются друг на друга. Например, на рисунке выше мы не можем рассмотреть shape. Для решения проблемы нажимаем на блок: в правом верхнем углу появляется информация о нём, в частности входные и выходные shape.

Рисунок 12. Информация о ноде

В левой части экрана мы видим инструменты для поиска блоков по имени, выделение цветом (полезно для просмотра блоков, работающих на gpu или cpu) и легенду.

Рисунок 13. Настройки отображения графа и легенда
Изображения и видео

Для логирования изображений достаточно вызвать метод add_image:

writer.add_image(tag='image', img_tensor=tensor, global_step=0)

Также можно указать параметр dataformats для изменения формата данных. Возможные значения: CHW, HWC, HW, WH.

Чтобы залогировать целый батч изображений, используем torchvision.utils.make_grid.

Рисунок 14. Залогированная картинка

Есть возможность логировать видеоролики без звука (гифки):

writer.add_video("video", video_tensor, fps=1)

Предварительно нужно установить библиотеку moviepy.

Shape video_tensor должен выглядеть как (батч, Ось времени, Цветовые каналы, Высота, Ширина). Количество каналов обязательно равно трём, следовательно, grayscale (1 канал) не поддерживается. Видеоролики находятся в Tensorboard там же, где и картинки.

Embeddings

Одна из самых полезных фичей Tensorboard — projector.

Projector — инструмент для визуализации эмбеддингов объектов.

Он позволяет спроецировать эмбеддинги на трёхмерную систему координат и кластеризовать их.

Для этого необходимо применить метод add_embedding. Первый аргумент здесь — сами эмбеддинги (например, выходы модели). Дополнительно можно передать изображения (они будут отображаться!), global_step и tag, который будем использовать для фильтра.

writer.add_embedding(model.forward(images), label_img=images, global_step=step, tag="emb")

Давайте посмотрим на результат во вкладке projector:

Рисунок 15. Вкладка projector. PCA-кластеризация эмбеддингов Cifar

По умолчанию мы видим данные, отраженные на трёхмерную ось с помощью PCA. Выглядит не очень впечатляюще 😟. Чтобы улучшить результат, кластеризуем их через TSNE. Этот процесс происходит на лету, поэтому мы можем видеть промежуточные результаты.

Рисунок 16. Настройки кластеризации
Рисунок 17. TSNE-кластеризация (не очень удачная, поскольку модель обучалась на малом количестве эпох)

Заключение

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

А ещё у него есть мощные и продуманные фичи (личные фавориты — это эмбеддинги и графы 🙂). Поэтому Tensorboard хорошо подойдёт для pet-проектов и небольших команд.

Кроме того, в этой статье мы не рассмотрели другие его полезные фичи — логирование аудио, PR-кривых и текстов.

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

Телеграм-канал

DeepSchool

Короткие посты по теории ML/DL, полезные
библиотеки и фреймворки, вопросы с собеседований
и советы, которые помогут в работе

Открыть Телеграм

Увидели ошибку?

Напишите нам в Telegram!