TensorFlow使用相同Generator Dataloader生成一致输入输出的方法
问题根因
你当前的实现出现输入标签不匹配的核心原因是:调用tf.data.Dataset.zip((random_dataset, random_dataset))时,TensorFlow会为两个传入的random_dataset分别初始化独立的生成器实例。迭代过程中会依次调用两个生成器的取值接口,每次执行tf.random.uniform都会更新TensorFlow的全局随机数状态,因此两个生成器拿到的是随机序列里相邻的两个不同值,无法对齐。
可行解决方案
下面按实现成本从低到高给出三个方案:
方案1:直接映射单数据集为输入标签对(最推荐)
完全不需要创建两个数据集,直接对单数据集做映射操作,将每条数据直接转为(输入, 标签)的配对格式,天然保证值完全一致:
def random_generator(): tf.random.set_seed(43) while True: yield tf.random.uniform((3,), 0, 1, dtype=tf.dtypes.float32, seed=32) random_dataset = tf.data.Dataset.from_generator( random_generator, output_types=tf.float32, output_shapes=(3,) # 新增映射逻辑,每条数据返回两份相同的值 ).map(lambda x: (x, x)) # 直接训练即可 model.fit(random_dataset, epochs=200, batch_size=32)
方案2:修改生成器直接返回配对数据
如果不想用map操作,也可以直接修改生成器的返回值,每次生成随机数后同时返回两份:
# 修改生成器逻辑 def random_generator(): tf.random.set_seed(43) while True: x = tf.random.uniform((3,), 0, 1, dtype=tf.dtypes.float32, seed=32) # 直接返回两份相同的随机数 yield x, x random_dataset = tf.data.Dataset.from_generator( random_generator, # 对应修改输出类型和形状声明 output_types=(tf.float32, tf.float32), output_shapes=((3,), (3,)) ) model.fit(random_dataset, epochs=200, batch_size=32)
方案3:缓存数据集后复制(适用于需要两个独立数据集的场景)
如果你确实需要两个独立可复用的同步数据集,可以先将有限长度的数据集缓存到内存/磁盘,再做zip操作,缓存后的数据集多次迭代返回的结果完全一致:
def random_generator(): tf.random.set_seed(43) while True: yield tf.random.uniform((3,), 0, 1, dtype=tf.dtypes.float32, seed=32) random_dataset = tf.data.Dataset.from_generator( random_generator, output_types=tf.float32, output_shapes=(3,) ) # 先取固定数量的样本做缓存,无限数据集无法直接缓存 cached_ds = random_dataset.take(10000).cache() # 缓存后的数据集多次迭代结果一致,zip后可保证值对齐 dataloader = tf.data.Dataset.zip((cached_ds, cached_ds)) model.fit(dataloader, epochs=200, batch_size=32)
内容的提问来源于stack exchange,提问作者Zahra Honjani
相关产品推荐
相关产品推荐

