如何避免model.fit中steps_per_epoch取整造成的样本浪费?
避免训练时丢弃样本的几种方法
针对你遇到的536个训练样本、batch size=32时每轮会丢弃24个样本的问题,除了调整batch size使其整除样本数外,还有以下几种可行方案:
使用TensorFlow Dataset API构建完整遍历的数据集
将训练数据转换为tf.data.Dataset,通过设置batch(32, drop_last=False)保留最后一个小批次,确保每个epoch遍历所有样本。示例代码:import tensorflow as tf # 从numpy数组构建数据集 train_dataset = tf.data.Dataset.from_tensor_slices((train_X, train_y)) # 打乱数据并分批,drop_last=False确保不丢弃剩余样本 train_dataset = train_dataset.shuffle(buffer_size=len(train_X)).batch(32, drop_last=False) # 训练时直接传入数据集,无需指定batch_size和steps_per_epoch results = model.fit(train_dataset, epochs=50, validation_data=(val_X, val_y), callbacks=callbacks)此方法会自动处理最后一个包含24个样本的批次,每个epoch都能完整遍历536个样本。
自定义Keras Sequence数据生成器
继承keras.utils.Sequence实现自定义生成器,手动控制每个批次的样本选取,确保所有样本都被用到。示例代码:from tensorflow.keras.utils import Sequence import numpy as np class FullDataGenerator(Sequence): def __init__(self, x_data, y_data, batch_size): self.x = x_data self.y = y_data self.batch_size = batch_size self.indices = np.arange(len(self.x)) np.random.shuffle(self.indices) def __len__(self): # 向上取整计算总批次,保证所有样本都被包含 return int(np.ceil(len(self.x) / self.batch_size)) def __getitem__(self, idx): # 获取当前批次的样本索引 batch_idx = self.indices[idx*self.batch_size : (idx+1)*self.batch_size] return self.x[batch_idx], self.y[batch_idx] def on_epoch_end(self): # 每个epoch结束后重新打乱样本顺序 np.random.shuffle(self.indices) # 初始化生成器 train_generator = FullDataGenerator(train_X, train_y, batch_size=32) # 传入生成器进行训练 results = model.fit(train_generator, epochs=50, validation_data=(val_X, val_y), callbacks=callbacks)生成器会自动处理最后一个小批次,每轮训练都能覆盖全部536个样本。
手动指定steps_per_epoch并允许小批次输入
若坚持使用原始的numpy数组输入方式,可手动计算总批次并设置steps_per_epoch=int(np.ceil(len(train_X)/32))(即17),同时确保模型的所有层支持可变大小的输入(大部分Keras内置层都支持)。示例代码:steps_per_epoch = int(np.ceil(len(train_X) / 32)) results = model.fit(train_X, train_y, batch_size=32, epochs=50, steps_per_epoch=steps_per_epoch, validation_data=(val_X, val_y), callbacks=callbacks)此方法会强制模型遍历17个批次,最后一个批次自动取剩余的24个样本,避免丢弃。
内容的提问来源于stack exchange,提问作者Kay
相关产品推荐
相关产品推荐

