在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里兼容性好太多了,步骤大概是这样:
- 把你的生成器转换成
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) - 用
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
相关产品推荐
相关产品推荐

