【tensorflow2.0】20.Dataset性能优化

    接着上篇文章讲一下Dataset的性能优化,训练深度学习模型常常会非常耗时。模型训练的耗时主要来自于两个部分,一部分来自数据准备,另一部分来自参数迭代。参数迭代过程的耗时通常依赖于GPU来提升, 而数据准备过程的耗时则可以通过构建高效的数据管道进行提升。

    下边是一些构建高效数据管道的建议:
1.prefetch方法:
原始方法执行,可以看到执行训练步骤涉及:
• 打开文件(如果尚未打开)
• 从文件中获取数据条目,
• 使用数据进行训练。
在这里插入图片描述
    prefetc h与训练步骤的预处理和模型执行重叠。当模型执行训练步骤时s,输入管道将读取步骤s+ 1的数据。这样做可以将步长时间减少到训练的最大值(而不是总和),并减少提取数据所需的时间。
在这里插入图片描述

"""
tf.data.Dataset.prefetch:它可用于将产生数据的时间与消耗数据的时间分开。特别是,map使用后台线程和内部缓冲区在请求输入之前,提前从输入数据集中预提取元素。注意:要预取的元素数量应等于(或可能大于)单个训练步骤消耗的ba tc h数量。可以手动调整此值,也可以将其设置为tf.data.experimental.AUTOTUNE ,
提示 tf.data运行时在运行时动态调整值的值。
"""
#定义解码函数
def _decode_and_resize(filename, label):
    image_string = tf.io.read_file(filename)            # 读取原始文件
    image_decoded = tf.image.decode_jpeg(image_string)  # 解码JPEG图片
    image_resized = tf.image.resize(image_decoded, [256, 256]) / 255.0
    return image_resized, label


batch_size = 32
train_dataset = tf.data.Dataset.from_tensor_slices((train_filenames, train_labels))
#计算时长函数
def benchmark(dataset, num_epochs=1):
    start_time = time.perf_counter()
    for epoch_num in range(num_epochs):
        for sample in dataset:
            # Performing a training step
            time.sleep(0.01)
    tf.print("Execution time:", time.perf_counter() - start_time)
benchmark(train_dataset.map(
    map_func=_decode_and_resize, 
    num_parallel_calls=tf.data.experimental.AUTOTUNE),
    num_epochs=1)
    
out:Execution time: 29.59943906086638

benchmark(
    train_dataset.map(
    map_func=_decode_and_resize, 
    num_parallel_calls=tf.data.experimental.AUTOTUNE)
    .prefetch(tf.data.experimental.AUTOTUNE),
    num_epochs=1
)

out:Execution time: 29.054936807737768

2.interleave 方法
tf.data.Dataset .interleave可以进行并行化数据加载,并交织其他数据集(例如数据文件读取器)的内容。可以通过cycle_length参数指定要重叠的数据集数量,而并行度则可以通过num_parallel_calls参数指定。使用num_parallel_calls可以并行加载多个数据集,从而减少了等待文件打开的时间。

"""
2.interleave的使用:
interleave(
    map_func, cycle_length=AUTOTUNE, block_length=1, num_parallel_calls=None,
    deterministic=None
)
interleave()是Dataset的类方法,所以interleave是作用在一个Dataset上的。
1.从Dataset中取出cycle_length个element,然后对这些element apply map_func, 得到cycle_length个新的Dataset对象。
2.从这些新生成的Dataset对象中取数据,每个Dataset对象一次取block_length个数据。
3.当新生成的某个Dataset的对象取尽时,从原Dataset中再取一个element,然后apply map_func,以此类推。
"""
filenames = ["./interleave_data/train.csv", "./interleave_data/eval.csv",
             "./interleave_data/train.csv", "./interleave_data/eval.csv",]
dataset = tf.data.Dataset.from_tensor_slices(filenames)

def data_func(line):
    line = tf.strings.split(line, sep = ",")
    return line

dataset_1 = dataset.interleave(lambda x:
    tf.data.TextLineDataset(x).skip(1).map(data_func),
    cycle_length=4, block_length=16)

benchmark(dataset_1,
    num_epochs=1)
out:Execution time: 25.970601931961596


dataset_2 = dataset.interleave(lambda x:
    tf.data.TextLineDataset(x).skip(1).map(data_func),
    num_parallel_calls=tf.data.experimental.AUTOTUNE,
    cycle_length=4, block_length=16)

benchmark(dataset_2,
    num_epochs=1)
out:Execution time: 25.826337882865033

3.使用map来多进程执行数据预处理
在这里插入图片描述

benchmark(
    train_dataset.map(
    map_func=_decode_and_resize, 
    num_parallel_calls=tf.data.experimental.AUTOTUNE)
)
out:Execution time: 29.13341431492455


benchmark(
    train_dataset.map(
    map_func=_decode_and_resize
    )
)
out:Execution time: 28.908936553196412
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值