使用SMOTE处理不平衡图像数据集时Jupyter内核崩溃问题求解
问题原因与解决方案
核心崩溃原因
你现有代码的三个问题直接导致内核崩溃:
- 输入类型不符合要求:
flow_from_directory返回的是DirectoryIterator迭代器对象,而SMOTE的fit_resample接口要求输入是已经加载到内存的二维样本特征数组,无法直接处理迭代器 - 维度太高算力爆炸:原始224*224的RGB图像拉平后单张特征维度达到150528,SMOTE基于K近邻做插值的时间复杂度是O(n²),数据集稍大就会出现计算时间过长、内存溢出的问题
- GPU完全没有被利用:imblearn的SMOTE原生仅支持CPU运算,你配备的16G显存完全没有参与计算,硬件优势无法发挥
另外补充:SMOTE本身是为表格数据设计的算法,直接对原始像素插值生成的合成图像没有语义价值,反而会引入训练噪声,本身就不推荐直接用于图像分类场景。
最优解决方案(无需使用SMOTE)
直接用类别权重+数据增强的方案替代SMOTE,完全兼容现有加载流程,不会出现内存溢出问题,还能充分利用GPU加速训练:
- 先根据数据集的类别分布计算平衡权重
from sklearn.utils.class_weight import compute_class_weight import numpy as np class_weights = compute_class_weight( class_weight = "balanced", classes = np.unique(train_generator.classes), y = train_generator.classes ) class_weight_dict = dict(zip(np.unique(train_generator.classes), class_weights))
- 模型训练时传入权重参数即可
model.fit( train_generator, class_weight=class_weight_dict, # 其余原有训练参数保持不变 )
如果少类样本数量太少,可以针对性给少类样本增加旋转、裁剪等增强策略,进一步提升模型泛化能力。
必须使用SMOTE的兼容方案
如果确实需要用到重采样逻辑,不要直接输入原始像素,先通过预训练CNN把图像降维到低维特征向量后再做SMOTE:
from tensorflow.keras.applications import MobileNetV2 from tensorflow.keras.models import Model from imblearn.over_sampling import SMOTE import numpy as np # 加载预训练特征提取器,去掉顶层分类头 base_model = MobileNetV2(input_shape=(224,224,3), include_top=False, pooling='avg') # 分批提取所有训练集的低维特征,避免一次性加载全部图像爆内存 all_feats = [] all_labels = [] for batch_idx in range(len(train_generator)): batch_x, batch_y = train_generator[batch_idx] batch_feat = base_model.predict(batch_x, verbose=0) all_feats.append(batch_feat) all_labels.append(batch_y) all_feats = np.concatenate(all_feats) all_labels = np.concatenate(all_labels) # 对1280维的低维特征做SMOTE,计算量下降两个数量级 smote = SMOTE() X_sm, y_sm = smote.fit_resample(all_feats, all_labels) # 后续使用重采样后的特征和标签训练分类头即可
内容的提问来源于stack exchange,提问作者maarij qamar
相关产品推荐
相关产品推荐

