TensorFlow CNN仅预测单一类别问题求助
问题
使用TensorFlow构建自定义CNN用于三分类任务,数据集无类别不平衡问题,但模型始终只预测单一类别。CNN架构如下:
model = tf.keras.Sequential([ Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 1), padding='same', data_format = 'channels_last'), BatchNormalization(), MaxPooling2D((2, 2), padding='same'), Conv2D(64, (3, 3), activation='relu', padding='same'), BatchNormalization(), MaxPooling2D((2, 2), padding='same'), Conv2D(128, (3, 3), activation='relu', padding='same'), BatchNormalization(), MaxPooling2D((2, 2), padding='same'), Conv2D(256, (3, 3), activation='relu', padding='same'), BatchNormalization(), MaxPooling2D((2, 2), padding='same'), Flatten(), Dense(256, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.01)), Dropout(0.5), Dense(128, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.01)), Dropout(0.5), Dense(3, activation='softmax') ])
已尝试调整学习率、添加BatchNormalization、Dropout及L2正则化,结果未改善。训练10轮后的分类报告:
precision recall f1-score support no 0.00 0.00 0.00 10000 sphere 0.33 1.00 0.50 10000 vort 0.00 0.00 0.00 10000 accuracy 0.33 30000 macro avg 0.11 0.33 0.17 30000 weighted avg 0.11 0.33 0.17 30000
有时预测的单一类别会变化,但始终只输出一类。数据集已做打乱处理:
BATCH_SIZE = 32 train_dataset = train_dataset.shuffle(buffer_size=train_len).batch(BATCH_SIZE) val_dataset = val_dataset.batch(BATCH_SIZE)
解决方案
匹配损失函数与标签编码方式
三分类任务用softmax输出层时,必须保证损失函数和标签编码对应:- 若标签是整数编码,用
SparseCategoricalCrossentropy:model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(), metrics=['accuracy']) - 若标签是one-hot编码,用
CategoricalCrossentropy:model.compile(optimizer='adam', loss=tf.keras.losses.CategoricalCrossentropy(), metrics=['accuracy'])
编码与损失函数不匹配会直接导致模型学习失效,偏向单一类别。
- 若标签是整数编码,用
降低正则化强度
当前L2正则化系数0.01过大,会过度压制模型特征学习能力。建议先将系数降到0.001或0.0001,甚至暂时移除正则化,验证模型是否能正常区分类别。检查数据预处理
- 确认输入数据是否归一化:未归一化的0-255像素值会导致训练不稳定,需缩放到
[0,1]区间:train_dataset = train_dataset.map(lambda x, y: (x / 255.0, y)) val_dataset = val_dataset.map(lambda x, y: (x / 255.0, y)) - 随机抽取样本验证标签分布,确保没有出现标签错位或单类别占比异常的情况。
- 确认输入数据是否归一化:未归一化的0-255像素值会导致训练不稳定,需缩放到
调整模型复杂度与训练轮数
当前模型规模较大,但仅训练10轮可能未收敛。可以先简化模型(比如减少卷积核数量或去掉一层全连接层),让模型先学会基础的类别区分能力,再逐步增加复杂度。同时将训练轮数提升到30-50轮,观察训练损失和精度的变化趋势。优化器与学习率调整
尝试更换优化器,比如用SGD配合0.001的学习率替代Adam,部分数据集上SGD的稳定性更好。也可以使用学习率调度器,让学习率随训练逐步降低:lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay( initial_learning_rate=0.001, decay_steps=10000, decay_rate=0.9) optimizer = tf.keras.optimizers.Adam(learning_rate=lr_schedule)验证数据集加载有效性
检查shuffle操作是否真正生效:随机查看几个训练批次的标签分布,确认每个批次都包含三类样本。同时验证验证集的标签是否正常,避免验证集本身存在异常。
内容的提问来源于stack exchange,提问作者Mohit Sharma
相关产品推荐
相关产品推荐

