Keras自定义图像数据生成器传入rescale参数触发TypeError
报错诱因与修复方案
报错核心诱因
- 该报错无复杂底层逻辑,本质是自定义类与Keras原生接口的命名混淆、参数定义不匹配导致的。
- 你自己基于
keras.utils.Sequence实现了一套按txt文件路径列表加载图像的生成逻辑,直接将类命名为ImageDataGenerator——这和Keras官方提供的、内置归一化、数据增强能力的图像生成器类名完全重名,编写后续训练代码时不自觉套用了原生类的传参习惯。 - 你的自定义类初始化函数
__init__仅声明了file_ids、batch_size两个入参,没有预留rescale参数的接收逻辑,Python在初始化类实例时会校验所有传入的关键词参数,碰到未定义的rescale参数就会直接抛出TypeError: __init__() got an unexpected keyword argument 'rescale'。 - 存在附带的隐藏问题:后续训练代码里调用的
flow_from_directory方法、train_dir/validation_dir路径变量,全是Keras原生生成器的专属用法,和你实现的“基于文件ID列表加载数据”的生成器逻辑完全不兼容,就算解决了当前的参数报错,后续还会触发“方法不存在”的报错。
对应修复步骤
- 重命名自定义生成器类,从根源上消除和Keras原生类的命名混淆,比如将类名修改为
CustomImageSequenceGenerator,原有内部逻辑不需要改动。 - 给自定义类补充归一化支持:在
__init__方法中增加rescale参数的接收逻辑,在图像读取完成后应用缩放系数,满足图像归一化的训练需求:class CustomImageSequenceGenerator(Sequence): 'Generates data for Keras' def __init__(self, file_ids, batch_size=32, rescale=None): # 新增rescale参数接收 self.file_ids = file_ids self.batch_size = batch_size self.rescale = rescale def __len__(self): return int(np.floor(len(self.file_ids) / self.batch_size)) def read_and_reisze_image(self, image_path): im = cv2.imread(image_path) im_resized = cv2.resize(im, (32, 32), interpolation=cv2.INTER_LINEAR) im_converted = cv2.cvtColor(im_resized, cv2.COLOR_BGR2RGB) # 增加缩放逻辑 if self.rescale is not None: im_converted = im_converted * self.rescale return im_converted def __getitem__(self, index): file_id = self.file_ids[index * self.batch_size:(index + 1) * self.batch_size] images = [self.read_and_reisze_image(f[0]) for f in file_id] labels = [int(f[1]) for f in file_id] labels = keras.utils.to_categorical(labels, num_classes=23) return np.asarray(images), labels - 修正训练阶段的实例化逻辑:删除所有原生生成器专属的
flow_from_directory调用,直接用拆分好的训练集、验证集文件ID列表实例化自定义生成器:# 先拆分原有的文件ID列表为训练、验证子集 train_file_ids, valid_file_ids = train_test_split(files_ids, test_size=0.2, random_state=42) # 实例化生成器,传入需要的rescale参数 train_generator = CustomImageSequenceGenerator(train_file_ids, batch_size=32, rescale=1/255.) valid_generator = CustomImageSequenceGenerator(valid_file_ids, batch_size=32, rescale=1/255.) - 修正模型定义与编译阶段的不匹配问题,避免修复完参数报错后触发形状、损失计算类错误:
- 自定义生成器将图像resize为32*32尺寸,要把CNN第一层
Conv2D的input_shape从(80,80,3)改为(32,32,3),匹配输入张量维度。 - 模型最后一层Dense层使用了
softmax激活函数,编译时损失函数的from_logits参数要改为False,否则会和softmax的逻辑冲突,导致损失计算结果错误。
修正后的编译代码:
model.compile( optimizer=keras.optimizers.Adam(), loss=keras.losses.CategoricalCrossentropy(from_logits=False), metrics=[keras.metrics.CategoricalAccuracy()] ) - 自定义生成器将图像resize为32*32尺寸,要把CNN第一层
- 直接调用
model.fit接口传入两个自定义生成器即可启动训练:history = model.fit( train_generator, epochs=50, validation_data=valid_generator )
内容的提问来源于stack exchange,提问作者Aitch
相关产品推荐
相关产品推荐

