使用ImageDataGenerator对肝脏超声图像数据集过采样时遇参数错误
问题原因
keras.preprocessing.image.ImageDataGenerator 类的初始化方法中没有oversample这个参数,传入该参数会触发TypeError。
解决数据集不平衡的可行方案
方案1:使用类权重(Class Weight)
在模型训练阶段,给样本量少的类别设置更高权重,让模型更重视少数类样本。
代码示例
from keras.preprocessing.image import ImageDataGenerator from sklearn.utils.class_weight import compute_class_weight import numpy as np # 初始化数据生成器(移除不存在的oversample参数) train_datagen = ImageDataGenerator( rescale=1./255, samplewise_center=True, samplewise_std_normalization=True, horizontal_flip=True, vertical_flip=True, rotation_range=90, brightness_range=[0.5, 1.5], zoom_range=0.2, shear_range=0.2 ) # 从目录加载训练数据 train_generator = train_datagen.flow_from_directory( 'train_dir', target_size=(224, 224), batch_size=32, class_mode='binary' # 根据任务调整,多分类用'categorical' ) # 计算类权重 class_weights = compute_class_weight( class_weight='balanced', classes=np.unique(train_generator.classes), y=train_generator.classes ) class_weight_dict = dict(enumerate(class_weights)) # 训练时传入类权重 model.fit( train_generator, epochs=20, class_weight=class_weight_dict )
方案2:手动过采样少数类
针对少数类样本单独做数据增强,生成更多样本平衡两类数据量。
代码示例
from keras.preprocessing.image import ImageDataGenerator import numpy as np # 为两类分别定义生成器:多数类仅基础缩放,少数类做全量增强 major_datagen = ImageDataGenerator(rescale=1./255) minor_datagen = ImageDataGenerator( rescale=1./255, samplewise_center=True, samplewise_std_normalization=True, horizontal_flip=True, vertical_flip=True, rotation_range=90, brightness_range=[0.5, 1.5], zoom_range=0.2, shear_range=0.2 ) # 加载两类数据 major_generator = major_datagen.flow_from_directory( 'train_dir/major_class', target_size=(224, 224), batch_size=32, class_mode='binary' ) minor_generator = minor_datagen.flow_from_directory( 'train_dir/minor_class', target_size=(224, 224), batch_size=32, class_mode='binary' ) # 计算少数类需要重复生成的次数,匹配多数类样本量 major_count = len(major_generator.filenames) minor_count = len(minor_generator.filenames) repeat_times = major_count // minor_count # 合并生成器,输出平衡的批次 def balanced_generator(): while True: x_major, y_major = next(major_generator) # 多次获取少数类批次并合并 x_minor_list, y_minor_list = [], [] for _ in range(repeat_times): x_min, y_min = next(minor_generator) x_minor_list.append(x_min) y_minor_list.append(y_min) x_minor = np.concatenate(x_minor_list) y_minor = np.concatenate(y_minor_list) # 合并两类数据并打乱 x_combined = np.concatenate([x_major, x_minor]) y_combined = np.concatenate([y_major, y_minor]) shuffle_idx = np.random.permutation(len(x_combined)) yield x_combined[shuffle_idx], y_combined[shuffle_idx] # 使用平衡生成器训练 model.fit( balanced_generator(), steps_per_epoch=major_count // 32, epochs=20 )
方案3:使用tf.data.Dataset实现平衡采样
利用TensorFlow数据集API,按指定比例从不同类别采样,实现类别平衡。
代码示例
import tensorflow as tf from keras.preprocessing.image import ImageDataGenerator # 从目录加载数据并转为tf.data.Dataset train_datagen = ImageDataGenerator(rescale=1./255) train_generator = train_datagen.flow_from_directory( 'train_dir', target_size=(224, 224), batch_size=32, class_mode='binary', shuffle=False ) dataset = tf.data.Dataset.from_generator( lambda: train_generator, output_types=(tf.float32, tf.float32), output_shapes=([None, 224, 224, 3], [None]) ) # 拆分出两类数据集 class_0_ds = dataset.unbatch().filter(lambda x, y: y == 0).batch(32) class_1_ds = dataset.unbatch().filter(lambda x, y: y == 1).batch(32) # 按1:1比例采样两类数据 balanced_ds = tf.data.experimental.sample_from_datasets( [class_0_ds, class_1_ds], weights=[0.5, 0.5] ).prefetch(tf.data.AUTOTUNE) # 训练模型 model.fit(balanced_ds, epochs=20)
内容的提问来源于stack exchange,提问作者hume
相关产品推荐
相关产品推荐

