如何在Tensorboard中加载选定范围的样本

时间:2019-10-07 20:29:29

标签: python tensorflow tensorboard

我有一个Tensorboard日志文件,其中包含500万个样本。 Tensorboard会在加载时对其进行降采样,以免出现内存不足的情况,但是可以使用--samples_per_plugin覆盖此行为并加载所有这些。如果这样做,我将耗尽内存。假设我要加载第一个样本而没有下采样(例如,如果我对培训开始时网络的详细情况感兴趣)。

有没有办法让Tensorboard仅加载指定的样本子集?我认为截至目前还没有命令行参数,但是也许有一种方法可以编辑日志文件或Tensorboard代码或其他解决方法?

1 个答案:

答案 0 :(得分:1)

我认为没有任何方法可以使TensorBoard做到这一点,但是可以“切片”事件文件。这些文件实际上是记录文件(仅包含事件数据而不是示例),因此您可以将它们读取为TFRecordDataset。显然,有第一条记录指示文件的版本号,但除此之外,它应该很简单。假设您只有要分割的事件,则可以使用类似这样的函数(TF 1.x,尽管在2.x中几乎相同):

import tensorflow as tf

def slice_events(input_path, output_path, skip, take):
    with tf.Graph().as_default():
        ds = tf.data.TFRecordDataset([str(input_path)])
        rec_first = ds.take(1).make_one_shot_iterator().get_next()
        ds_data = ds.skip(skip + 1).take(take)
        rec_data = ds_data.batch(1000).make_one_shot_iterator().get_next()
        with tf.io.TFRecordWriter(str(output_path)) as writer, tf.Session() as sess:
            writer.write(sess.run(rec_first))
            while True:
                try:
                    for ev in sess.run(rec_data):
                        writer.write(ev)
                except tf.errors.OutOfRangeError: break

这将从现有的文件中创建一个新的事件文件,其中将丢弃第一个skip个事件,然后保存之后的take个事件。您可以使用其他Dataset操作来选择要保留的数据。例如,下采样可以通过以下方式完成:

ds_data = ds.skip(1).window(1, 5).unbatch()  # Takes one in five events

您可以制作一个脚本来将所有事件文件切片到一个目录中,然后将它们保存到具有相同结构的另一个文件中,例如:

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

# slice_events.py

import sys
import os
from pathlib import Path
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'  # Not necessary to use GPU
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'  # Avoid log messages

def slice_events(input_path, output_path, skip, take):
    # Import here to avoid loading on error
    import tensorflow as tf
    # Code from before...

def slice_events_dir(input_dir, output_dir, skip, take):
    input_dir = Path(input_dir)
    output_dir = Path(output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)
    for ev_file in input_dir.glob('**/*.tfevents*'):
        out_file = Path(output_dir, ev_file.relative_to(input_dir))
        out_file.parent.mkdir(parents=True, exist_ok=True)
        slice_events(ev_file, out_file, skip, take)

if __name__ == '__main__':
    if len(sys.argv) != 5:
        print(f'{sys.argv[0]} <input dir> <output dir> <skip> <take>', file=sys.stderr)
        sys.exit(1)
    input_dir, output_dir, skip, take = sys.argv[1:]
    skip = int(skip)
    take = int(take)
    slice_events_dir(input_dir, output_dir, skip, take)

然后您将其用作

$ python slice_events.py log log_sliced 100 1000

请注意,这是在简单的情况下进行的,在该情况下,您只需要进行一系列类似的事件进行切片。如果您有其他类型的事件(例如,图形本身),或者同一文件中存在多种类型的交错事件,或者其他原因,那么您就需要根据需要调整逻辑。