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

在Google Colab CPU训练神经网络:第二个epoch无法启动

你的fit_generator第二个epoch卡住的问题分析与解决

嘿,我来帮你捋一捋这个问题——你在Colab CPU上用fit_generator训练,第一个epoch正常跑,第二个就卡着不动还没崩溃,这种情况我之前也碰到过,大概率不是代码逻辑错了,而是多进程在Colab受限环境下的兼容性问题,下面给你拆解原因和修复方案:

核心原因推测

  • 多进程资源过载:Colab的CPU实例一般只有2核左右,你设置了workers=6,远超可用核心数,进程之间抢资源抢得厉害,甚至会出现死锁,导致第二个epoch启动不了。
  • fit_generator的过时缺陷:这个API在TensorFlow 2.x里已经被标记为废弃了,它的多进程实现比较老旧,在Colab这种容器化环境里很容易出现进程挂起的问题。

具体修复步骤

第一步:先调低多进程参数试试

先把多进程关掉或者调小worker数量,看看能不能正常跑完所有epoch:

model.fit_generator(
    generator=training_generator,
    validation_data=validation_generator,
    steps_per_epoch=num_train_samples // 128,
    validation_steps=num_val_samples // 128,
    epochs=10,
    use_multiprocessing=False,  # 先关闭多进程
    workers=1  # 单进程运行
)

如果单进程没问题,再慢慢把workers调到2(Colab CPU的核心上限),同时开启use_multiprocessing=True,观察情况。

第二步:换成更稳定的model.fit()+tf.data.Dataset(推荐)

既然fit_generator已经过时,不如直接迁移到tf.data管道,这在Colab里兼容性好太多了,步骤大概是这样:

  1. 把你的生成器转换成tf.data.Dataset:
    import tensorflow as tf
    
    # 替换成你自己的数据类型和形状
    train_dataset = tf.data.Dataset.from_generator(
        lambda: training_generator,
        output_types=(tf.float32, tf.float32),
        output_shapes=((None, 224, 224, 3), (None, 10))
    ).batch(128)
    
    val_dataset = tf.data.Dataset.from_generator(
        lambda: validation_generator,
        output_types=(tf.float32, tf.float32),
        output_shapes=((None, 224, 224, 3), (None, 10))
    ).batch(128)
    
  2. 用model.fit()训练:
    model.fit(
        train_dataset,
        validation_data=val_dataset,
        steps_per_epoch=num_train_samples // 128,
        validation_steps=num_val_samples // 128,
        epochs=10,
        use_multiprocessing=True,
        workers=2  # 匹配Colab CPU的核心数
    )
    

tf.data的多进程实现是重新设计的,比fit_generator稳定很多,基本不会出现这种卡住的情况。

第三步:检查自定义生成器的状态重置

如果你的生成器是自己写的keras.utils.Sequence子类,要确保每个epoch结束后正确重置状态,比如打乱数据索引:

class MyTrainingGenerator(keras.utils.Sequence):
    def __init__(self, data, labels, batch_size):
        self.data = data
        self.labels = labels
        self.batch_size = batch_size
        self.on_epoch_end()  # 初始化时就打乱一次

    def on_epoch_end(self):
        # 每个epoch结束后重新打乱索引,保证数据顺序随机
        self.indexes = np.arange(len(self.data))
        np.random.shuffle(self.indexes)

    def __getitem__(self, idx):
        # 根据索引取batch数据
        batch_indexes = self.indexes[idx*self.batch_size : (idx+1)*self.batch_size]
        batch_data = self.data[batch_indexes]
        batch_labels = self.labels[batch_indexes]
        return batch_data, batch_labels

    def __len__(self):
        # 返回每个epoch的步数
        return len(self.data) // self.batch_size

要是生成器在epoch结束后没重置,可能导致第二个epoch拿不到数据,就会一直卡着。


另外提一句你说的GPU环境下的FileNotFoundError,要是之后想换回GPU训练,可以检查下数据路径是不是在Colab的临时存储里——有时候CPU和GPU实例的文件系统是分开的,或者是不是挂载的谷歌云盘路径有问题?不过先解决CPU下的卡住问题更要紧。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 07:12:28