You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Python生成器结合TensorFlow的‘generator already executing’错误?

解决ValueError: generator already executing异常的方案

问题原因

异常根源在于tf.data.Dataset.from_generator的使用方式错误:你直接传入了已实例化的生成器对象(train_gen、val_gen),但TensorFlow要求该参数是能创建新生成器实例的函数。AutoKeras在训练流程中(如数据解析、多轮训练、验证环节)会多次迭代数据集,同一个生成器实例无法被同时调用,因此触发此异常。

解决方案1:修改生成器传入逻辑(推荐)

调整代码,让from_generator每次调用时都生成新的生成器实例:

1. 重构生成器创建函数

def create_generator_funcs(folder_path, batch_size, num_classes, validation_split=0.2):
    files = [os.path.join(folder_path, f) for f in os.listdir(folder_path) if f.endswith('.dat')]
    train_files, validation_files = train_test_split(files, test_size=validation_split)
    
    # 返回创建生成器的函数,每次调用生成新实例
    def train_gen_func():
        return data_generator(train_files, batch_size, num_classes)
    
    def val_gen_func():
        return data_generator(validation_files, batch_size, num_classes)
    
    return train_gen_func, val_gen_func

2. 修改数据集创建代码

if __name__ == "__main__":
    data_folder = r'/home/my_username/my_project_v2_original_data'
    train_gen_func, val_gen_func = create_generator_funcs(data_folder, BATCH_SIZE, NUM_OF_CLASSES)
    
    train_dataset = tf.data.Dataset.from_generator(
        train_gen_func,
        output_signature=(
            tf.TensorSpec(shape=(BATCH_SIZE, NUM_OF_FEATURES), dtype=tf.float32),
            tf.TensorSpec(shape=(BATCH_SIZE, NUM_OF_CLASSES), dtype=tf.float32)
        )
    )

    validation_dataset = tf.data.Dataset.from_generator(
        val_gen_func,
        output_signature=(
            tf.TensorSpec(shape=(BATCH_SIZE, NUM_OF_FEATURES), dtype=tf.float32),
            tf.TensorSpec(shape=(BATCH_SIZE, NUM_OF_CLASSES), dtype=tf.float32)
        )
    )

解决方案2:用类封装生成器(替代方案)

通过类封装生成器逻辑,每次实例化类都会生成独立的生成器:

class DataGenerator:
    def __init__(self, file_paths, batch_size, num_classes):
        self.file_paths = file_paths
        self.batch_size = batch_size
        self.num_classes = num_classes
    
    def __call__(self):
        while True:
            for file_path in self.file_paths:
                x, y = load_data(file_path)
                for i in range(0, len(x), self.batch_size):
                    end = i + self.batch_size
                    batch_x = x[i:end]
                    batch_y = y[i:end]
                    if batch_x.shape[0] < self.batch_size:
                        padding = self.batch_size - batch_x.shape[0]
                        batch_x = np.pad(batch_x, ((0, padding), (0, 0)), mode='constant', constant_values=0)
                        batch_y = np.pad(batch_y, ((0, padding), (0, 0)), mode='constant', constant_values=0)
                    yield batch_x, batch_y

主函数中使用类生成器

if __name__ == "__main__":
    data_folder = r'/home/my_username/my_project_v2_original_data'
    files = [os.path.join(data_folder, f) for f in os.listdir(data_folder) if f.endswith('.dat')]
    train_files, validation_files = train_test_split(files, test_size=0.2)
    
    train_dataset = tf.data.Dataset.from_generator(
        DataGenerator(train_files, BATCH_SIZE, NUM_OF_CLASSES),
        output_signature=(
            tf.TensorSpec(shape=(BATCH_SIZE, NUM_OF_FEATURES), dtype=tf.float32),
            tf.TensorSpec(shape=(BATCH_SIZE, NUM_OF_CLASSES), dtype=tf.float32)
        )
    )

    validation_dataset = tf.data.Dataset.from_generator(
        DataGenerator(validation_files, BATCH_SIZE, NUM_OF_CLASSES),
        output_signature=(
            tf.TensorSpec(shape=(BATCH_SIZE, NUM_OF_FEATURES), dtype=tf.float32),
            tf.TensorSpec(shape=(BATCH_SIZE, NUM_OF_CLASSES), dtype=tf.float32)
        )
    )

额外优化建议

  • 将output_signature中的shape从None改为固定的(BATCH_SIZE, ...),因为生成器中已通过padding保证批次大小一致,能帮助TensorFlow优化数据处理流程。
  • 在生成器中添加tf.convert_to_tensor,直接返回TensorFlow张量,减少数据转换开销。

内容的提问来源于stack exchange,提问作者user366312

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 01:12:03