Как вы редактируете существующую сводку о потере обучения в Tensorboard? - PullRequest
2 голосов
/ 05 февраля 2020

Я обучил свою сеть и сгенерировал некоторые потери при обучении / проверке, которые я сохранил с помощью следующего примера кода (пример только потери при обучении, проверка совершенно эквивалентна):

valid_summary_writer = tf.summary.create_file_writer("/path/to/logs/")
with train_summary_writer.as_default():
    tf.summary.scalar('Training Loss', data=epoch_loss, step=current_step)

После обучения я бы затем нравится просматривать кривые потерь с помощью Tensorboard. Однако, поскольку я сохранил кривые потерь под именами «Потеря обучения» и «Потеря проверки», эти кривые построены на отдельных графиках. Я знаю, что мне нужно изменить имя на «потеря», чтобы решить эту проблему для будущих записей в каталог журналов. Но как мне отредактировать мои существующие файлы журналов для потерь обучения / проверки, чтобы учесть это?

Я попытался изменить решение следующего поста: { ссылка }, которое редактирует шаги файл журнала и перезаписывает файл; где моя версия предполагает изменение тегов в файле. Но у меня не было успеха в этой области. Также требуется импортировать старый код Tensorflow через tf.compat.v1. Есть ли способ добиться этого (возможно, в TF 2.X)?

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

--- === РЕДАКТИРОВАТЬ === ---

Мне удалось решить проблему, используя код из @ jhedesa

Мне пришлось немного изменить способ вызова функции "rename_events_dir", так как я использую Tensorflow совместно в ноутбуке Google Colab. Чтобы сделать это, я изменил последнюю часть кода, которая гласила:

if __name__ == '__main__':
    if len(sys.argv) != 5:
        print(f'{sys.argv[0]} <input dir> <output dir> <old tags> <new tag>',
              file=sys.stderr)
        sys.exit(1)
    input_dir, output_dir, old_tags, new_tag = sys.argv[1:]
    old_tags = old_tags.split(';')
    rename_events_dir(input_dir, output_dir, old_tags, new_tag)
    print('Done')

Чтобы прочитать это:

rootpath = '/path/to/model/'
dirlist = [dirname for dirname in os.listdir(rootpath) if dirname not in ['train', 'valid']]
for dirname in dirlist:
  rename_events_dir(rootpath + dirname + '/train', rootpath + '/train', 'Training Loss', 'loss')
  rename_events_dir(rootpath + dirname + '/valid', rootpath + '/valid', 'Validation Loss', 'loss')

Обратите внимание, что я дважды вызывал "rename_events_dir", один раз для редактирования тегов для потери обучения, и один раз для тегов потери проверки. Я мог бы использовать предыдущий метод вызова кода, установив "old_tags = 'Training Loss; Validation Loss'" и используя "old_tags = old_tags.split (';')" для разделения тегов. Я использовал свой метод просто, чтобы понять код и то, как он обрабатывает данные.

1 Ответ

1 голос
/ 05 февраля 2020

Как уже упоминалось в Как загрузить выбранный диапазон выборок в Tensorboard , события TensorBoard на самом деле хранятся в файлах записей, поэтому вы можете их читать и обрабатывать как таковые. Вот скрипт, похожий на тот, который выложен там, но с целью переименования событий и обновленный для работы в TF 2.x.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# rename_events.py

import sys
from pathlib import Path
import os
# Use this if you want to avoid using the GPU
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
import tensorflow as tf
from tensorflow.core.util.event_pb2 import Event

def rename_events(input_path, output_path, old_tags, new_tag):
    # Make a record writer
    with tf.io.TFRecordWriter(str(output_path)) as writer:
        # Iterate event records
        for rec in tf.data.TFRecordDataset([str(input_path)]):
            # Read event
            ev = Event()
            ev.MergeFromString(rec.numpy())
            # Check if it is a summary
            if ev.summary:
                # Iterate summary values
                for v in ev.summary.value:
                    # Check if the tag should be renamed
                    if v.tag in old_tags:
                        # Rename with new tag name
                        v.tag = new_tag
            writer.write(ev.SerializeToString())

def rename_events_dir(input_dir, output_dir, old_tags, new_tag):
    input_dir = Path(input_dir)
    output_dir = Path(output_dir)
    # Make output directory
    output_dir.mkdir(parents=True, exist_ok=True)
    # Iterate event files
    for ev_file in input_dir.glob('**/*.tfevents*'):
        # Make directory for output event file
        out_file = Path(output_dir, ev_file.relative_to(input_dir))
        out_file.parent.mkdir(parents=True, exist_ok=True)
        # Write renamed events
        rename_events(ev_file, out_file, old_tags, new_tag)

if __name__ == '__main__':
    if len(sys.argv) != 5:
        print(f'{sys.argv[0]} <input dir> <output dir> <old tags> <new tag>',
              file=sys.stderr)
        sys.exit(1)
    input_dir, output_dir, old_tags, new_tag = sys.argv[1:]
    old_tags = old_tags.split(';')
    rename_events_dir(input_dir, output_dir, old_tags, new_tag)
    print('Done')

Вы бы использовали его так:

> python rename_events.py my_log_dir renamed_log_dir "Training Loss;Validation Loss" loss
...