复现DCNN论文模型时训练精度损失停滞的代码修正方法
问题原因与修正方案
你的代码存在4个核心错误,直接导致模型参数无法更新、训练过程中损失和精度完全卡死:
- 输出层激活函数与任务、损失函数完全不匹配:二分类像素级分割任务下,若最后一层卷积输出通道为1,必须使用
sigmoid作为激活函数,搭配binary_crossentropy损失。你当前给单通道输出接softmax激活,由于softmax是对通道维度做归一化,单通道下输出值永远为1,反向传播梯度为0,参数从始至终不会更新——你观察到的76%左右的精度就是数据集里多数类的占比,模型相当于一直固定预测多数类,完全没有学习。 - 未实现论文提到的50%步长设置:50%步长指卷积滑动步长为卷积核尺寸的1/2,你第一层卷积核大小为8*8,对应步长应为
(4,4),你当前使用默认步长1,不符合论文结构。注意使用该步长后特征图尺寸会缩小为原尺寸的1/4,需要添加上采样层恢复到原输入尺寸,才能匹配像素级分类的标签维度。 - 输入未做归一化:12通道的输入图像必须先做归一化处理(比如将所有像素值缩放到0~1区间,或逐通道做Z-score标准化),否则数值范围过大容易导致梯度消失/爆炸,阻碍模型收敛。
- 标签维度不匹配:单通道sigmoid输出的设置下,你的训练/验证标签形状必须为
(样本数, 256, 256, 1),标签值为0或1,维度或数值范围错误也会导致训练异常。
修正后的可运行代码
import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv2D, UpSampling2D import numpy as np # --------------- 数据预处理部分 --------------- # 对输入做0-1归一化,可根据数据实际值域调整为Z-score标准化 x_train = x_train.astype('float32') / np.max(x_train) x_val = x_val.astype('float32') / np.max(x_val) # 对齐标签维度,确保标签值为0/1 y_train = y_train.reshape(-1, 256, 256, 1).astype('float32') y_val = y_val.reshape(-1, 256, 256, 1).astype('float32') # --------------- 模型构建 --------------- cnn = Sequential() # 第一层8*8卷积,步长4实现50%滑动重叠 cnn.add(Conv2D(100, (8,8), strides=(4,4), input_shape = (256, 256, 12), activation = 'relu', padding = 'SAME')) cnn.add(Conv2D(50, (1,1), activation = 'relu', padding='SAME')) cnn.add(Conv2D(30, (1,1), activation = 'relu', padding='SAME')) cnn.add(Conv2D(15, (1,1), activation = 'relu', padding='SAME')) # 上采样4倍恢复到原输入256*256尺寸,匹配像素级输出要求 cnn.add(UpSampling2D(size=(4,4))) # 输出层单通道,用sigmoid激活做二分类 cnn.add(Conv2D(1, (1,1), activation = 'sigmoid', padding='SAME')) cnn.compile(optimizer = tf.keras.optimizers.Adam(learning_rate=1e-4), loss = 'binary_crossentropy', metrics = ['accuracy']) model_checkpoint_callback = tf.keras.callbacks.ModelCheckpoint( filepath="dcnn_model.h5", verbose=1, save_weights_only=True, monitor='val_accuracy', mode='max', save_best_only=True) # --------------- 模型训练 --------------- cnn.fit(x_train,y_train, batch_size=5, epochs=30, shuffle=True, validation_data=(x_val,y_val), callbacks=[model_checkpoint_callback])
额外调优建议
- 初始学习率建议设为1e-4,Adam优化器默认的1e-3学习率对于90张样本的小数据集分割任务步长过大,容易导致收敛不稳定
- 如果数据集存在类别不平衡问题(某一类像素占比远高于另一类),可以给损失函数加类别权重,或者把监控指标换成
MeanIoU,全局精度不能真实反映像素级分类的效果 - 正式训练前建议打印一次
cnn.summary(),确认最后一层输出形状为(None,256,256,1),和标签形状完全匹配
内容的提问来源于stack exchange,提问作者Mandy Chu
相关产品推荐
相关产品推荐

