我有一个Tensorboard日志文件,其中包含500万个样本。 Tensorboard会在加载时对其进行降采样,以免出现内存不足的情况,但是可以使用--samples_per_plugin
覆盖此行为并加载所有这些。如果这样做,我将耗尽内存。假设我要加载第一个样本而没有下采样(例如,如果我对培训开始时网络的详细情况感兴趣)。
有没有办法让Tensorboard仅加载指定的样本子集?我认为截至目前还没有命令行参数,但是也许有一种方法可以编辑日志文件或Tensorboard代码或其他解决方法?
答案 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
请注意,这是在简单的情况下进行的,在该情况下,您只需要进行一系列类似的事件进行切片。如果您有其他类型的事件(例如,图形本身),或者同一文件中存在多种类型的交错事件,或者其他原因,那么您就需要根据需要调整逻辑。