Keras使用ImageDataGenerator训练时报y参数不支持错误
问题根源
这个报错的核心触发原因是:Keras中当你给model.fit()传入的输入是keras.utils.Sequence类型对象(flow_from_directory返回的目录迭代器就属于这类对象)时,不支持再单独传入y参数传标签。这种输入模式下,要求传入的Sequence对象本身每次迭代必须返回(输入批次, 对应标签批次)的元组,你现在把输入X和标签Y拆成了两个独立的Sequence对象,分别传给fit的x和y位置,就会直接抛出这个错误。
除了这个直接触发报错的问题,你写的加载代码还有几个隐藏逻辑错误,就算绕开报错也无法正常训练:
- 验证集标签的加载参数写错:训练集标签从
train_cleaned_path下的output文件夹读取,验证集标签却错误指向同路径下的train_cleaned文件夹;同时验证集标签生成器的class_mode填了不存在的合法值'output',正确的返回图像本身作为标签的取值应该是'input'。 - 样本配对无保证:两个独立的生成器分别加载X和Y,只要shuffle规则、文件排序逻辑、种子值有一点不一致,就会出现输入图和标注图错配的问题,训练出来的模型完全无效。
- 参数重复传无效:你已经用
flow_from_directory生成批次数据,又在fit里传了batch_size=16,这个参数仅对数组形式的输入生效,传入Sequence时不会起作用,批大小需要在生成器初始化时设置。
修正方法
最稳妥的方案是自定义一个配对图像的Sequence数据集类,同时读取对应路径下的输入图和标注图,从根源上保证样本配对正确,也能天然适配fit的输入要求。
- 先导入依赖
from tensorflow.keras.utils import Sequence from PIL import Image import numpy as np import os from sklearn.model_selection import train_test_split
- 实现配对图像加载的数据集类
class PairedImgDataset(Sequence): def __init__(self, input_dir, target_dir, batch_size, img_size, shuffle=True, file_list=None): self.input_dir = input_dir self.target_dir = target_dir self.batch_size = batch_size self.img_size = img_size self.shuffle = shuffle # 加载指定的文件名列表,用于训练/验证集划分 self.file_list = file_list if file_list is not None else [ f for f in os.listdir(input_dir) if f.lower().endswith(('.png', '.jpg', '.jpeg')) ] self.on_epoch_end() def __len__(self): # 返回单个epoch包含的batch数量 return len(self.file_list) // self.batch_size def on_epoch_end(self): # 每个epoch结束后打乱样本顺序 self.indexes = np.arange(len(self.file_list)) if self.shuffle: np.random.shuffle(self.indexes) def __getitem__(self, idx): # 加载当前batch的所有样本 batch_idx = self.indexes[idx*self.batch_size : (idx+1)*self.batch_size] batch_x, batch_y = [], [] for i in batch_idx: fname = self.file_list[i] # 读取输入图,resize后归一化到0-1区间 x = np.array(Image.open(os.path.join(self.input_dir, fname)).convert('RGB').resize(self.img_size)) / 255.0 # 读取同文件名的标注图,保证和输入严格配对 y = np.array(Image.open(os.path.join(self.target_dir, fname)).convert('RGB').resize(self.img_size)) / 255.0 batch_x.append(x) batch_y.append(y) return np.array(batch_x), np.array(batch_y)
- 划分训练/验证集,初始化数据加载器
# 按你的实际路径修改配置 INPUT_FOLDER = "input文件夹的完整路径" TARGET_FOLDER = "output文件夹的完整路径" BATCH_SIZE = 16 IMG_SHAPE = (256, 256) # 替换为你模型要求的输入尺寸 VAL_SPLIT = 0.2 # 按比例划分训练/验证集对应的文件名 all_imgs = [f for f in os.listdir(INPUT_FOLDER) if f.lower().endswith(('.png', '.jpg', '.jpeg'))] train_files, val_files = train_test_split(all_imgs, test_size=VAL_SPLIT, random_state=42) # 初始化训练、验证数据集 train_ds = PairedImgDataset( input_dir=INPUT_FOLDER, target_dir=TARGET_FOLDER, batch_size=BATCH_SIZE, img_size=IMG_SHAPE, shuffle=True, file_list=train_files ) val_ds = PairedImgDataset( input_dir=INPUT_FOLDER, target_dir=TARGET_FOLDER, batch_size=BATCH_SIZE, img_size=IMG_SHAPE, shuffle=False, file_list=val_files )
- 调用fit训练,不需要单独传y和batch_size
history = conv_NN.fit( train_ds, validation_data=val_ds, epochs=20, callbacks=[early_stop, tensorboard_callback], verbose=1 )
如果你坚持要用
flow_from_directory实现,必须保证X和Y的两个生成器参数完全一致(相同的seed、shuffle设为False、相同batch_size、相同文件排序逻辑),再用tf.data.Dataset.zip把两个生成器打包成返回(x,y)的数据集传入fit,但这种方式很容易因为参数不匹配出现样本错配,不推荐使用。
内容的提问来源于stack exchange,提问作者user9113784
相关产品推荐
相关产品推荐

