Jia*_*nbo 6 python tensorflow tensorflow-datasets
您好我正在研究tensorflow中的数据集API,我对datat.map()函数有一个问题,该函数执行数据预处理.
file_name = ["image1.jpg", "image2.jpg", ......]
im_dataset = tf.data.Dataset.from_tensor_slices(file_names)
im_dataset = im_dataset.map(lambda image:tuple(tf.py_func(image_parser(), [image], [tf.float32, tf.float32, tf.float32])))
im_dataset = im_dataset.batch(batch_size)
iterator = im_dataset.make_initializable_iterator()
Run Code Online (Sandbox Code Playgroud)
数据集接收图像名称并将其解析为3个张量(关于图像的3个信息).
如果我的训练文件夹中有大量图像,预处理它们需要很长时间.我的问题是,由于数据集API据说是为高效的输入管道而设计的,因此在我将它们提供给我的工作人员(比如说GPU)之前对整个数据集进行预处理,或者每次我只预处理一批图像调用iterator.get_next()?
如果预处理管道很长且输出很小,则处理后的数据应该适合内存.如果是这种情况,您可以使用tf.data.Dataset.cache
将已处理的数据缓存在内存或文件中.
从官方表现指南:
该
tf.data.Dataset.cache
改造可以缓存的数据集,在内存或本地存储.如果传递给映射转换的用户定义函数很昂贵,只要结果数据集仍然适合内存或本地存储,就可以在映射转换后应用缓存转换.如果用户定义的函数增加了存储数据集超出缓存容量所需的空间,请考虑在训练作业之前预处理数据以减少资源使用.
以下是每个预处理需要花费大量时间(0.5秒)的示例.数据集上的第二个时期将比第一个时期快得多
def my_fn(x):
time.sleep(0.5)
return x
def parse_fn(x):
return tf.py_func(my_fn, [x], tf.int64)
dataset = tf.data.Dataset.range(5)
dataset = dataset.map(parse_fn)
dataset = dataset.cache() # cache the processed dataset, so every input will be processed once
dataset = dataset.repeat(2) # repeat for multiple epochs
res = dataset.make_one_shot_iterator().get_next()
with tf.Session() as sess:
for i in range(10):
# First 5 iterations will take 0.5s each, last 5 will not
print(sess.run(res))
Run Code Online (Sandbox Code Playgroud)
如果要将缓存数据写入文件,可以提供以下参数cache()
:
dataset = dataset.cache('/tmp/cache') # will write cached data to a file
Run Code Online (Sandbox Code Playgroud)
这将允许您只处理数据集一次,并对数据运行多个实验而无需再次重新处理它.
警告:缓存到文件时必须小心.如果您更改数据但保留/tmp/cache.*
文件,它仍将读取缓存的旧数据.例如,如果我们使用上面的数据并更改要处理的数据范围[10, 15]
,我们仍将获取以下数据[0, 5]
:
dataset = tf.data.Dataset.range(10, 15)
dataset = dataset.map(parse_fn)
dataset = dataset.cache('/tmp/cache')
dataset = dataset.repeat(2) # repeat for multiple epochs
res = dataset.make_one_shot_iterator().get_next()
with tf.Session() as sess:
for i in range(10):
print(sess.run(res)) # will still be in [0, 5]...
Run Code Online (Sandbox Code Playgroud)
每当要缓存的数据发生更改时,始终删除缓存的文件.
可能出现的另一个问题是,如果在缓存所有数据之前中断脚本.您将收到如下错误:
AlreadyExistsError(参见上面的回溯):似乎有一个并发缓存迭代器正在运行 - 缓存锁定文件已经存在('/tmp/cache.lockfile').如果您确定没有其他正在运行的TF计算正在使用此缓存前缀,请删除锁定文件并重新初始化迭代器.
确保您处理整个数据集以拥有整个缓存文件.