多任务属性分类模型验证精度异常:固定值或交替补值求助
多任务属性分类模型验证精度异常排查
问题背景
我正在实现一个图像属性分类的多任务学习模型:输入为512维图像特征,每张图像对应40个二元属性标注;模型结构是输入层后接一个共享密集层,再分40个独立属性分支,每个分支使用二元交叉熵损失,最后一层用sigmoid输出属性存在概率。
当前异常现象:训练损失(loss)与验证损失(val_loss)逐步降低,训练精度(acc)处于正常范围,但验证精度(val_acc)始终固定在某个值或其补值(如0.88与0.12交替/固定)。
模型代码
def subnet(shared_layers_output, i): att_branch = Dense(512, name='dense_'+str(i)+'_1')(shared_layers_output) att_branch = ReLU()(att_branch) att_branch = BatchNormalization()(att_branch) att_branch = Dropout(0.5)(att_branch) att_branch = Dense(512, name='dense_'+str(i)+'_2')(att_branch) att_branch = ReLU()(att_branch) att_branch = BatchNormalization()(att_branch) att_branch = Dropout(0.5)(att_branch) branch_output = Dense(1, name=att_list[i], activation='sigmoid')(att_branch) return branch_output def multi_task_model(): #Input input_layer = Input(shape=(512,), name='input_layer') #Camada compartilhada (1 única) shared_x = Dense(512, name='shared_dense_layer')(input_layer) shared_x = ReLU()(shared_x) shared_x = BatchNormalization()(shared_x) shared_x = Dropout(0.5)(shared_x) branch_outputs = list() for i in range(40): branch_outputs.append(subnet(shared_x, i)) model = Model(input_layer, branch_outputs, name='model') return model
训练参数与异常指标示例
训练参数
Train and test input shape: (n_samples, 512) Train and test labels input shape: (40, n_samples) Learning rate: 1e-03
某属性分支5个epoch指标
loss val_loss acc val_acc 0 0.422385 1.949578 0.864272 0.8873 1 0.354094 151.987991 0.888797 0.1127 2 0.354356 58.867992 0.888797 0.1127 3 0.352891 94.257980 0.888797 0.1127 4 0.353390 10.997763 0.888797 0.1127
排查思路与解决方法
1. 标签输入格式错误(最可能原因)
当前标签形状为(40, n_samples),但Keras多任务模型要求标签为列表形式:每个元素对应一个分支的(n_samples,)或(n_samples,1)形状,否则模型会把样本维度与属性维度混淆,导致预测完全错位,出现精度跳变到补值的情况。
- 修正方法:将标签转置后拆分为列表
# 原标签shape=(40, n_samples),转置为(n_samples,40)后拆分 train_labels = [train_labels.T[:, i] for i in range(40)] val_labels = [val_labels.T[:, i] for i in range(40)]
2. 精度计算逻辑错误
多任务场景下默认的accuracy指标计算逻辑不适用,需为每个分支单独指定二元精度指标:
- 修正方法:编译模型时配置分支专属指标
from tensorflow.keras.metrics import BinaryAccuracy model.compile( optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4), loss='binary_crossentropy', metrics=[[BinaryAccuracy(name=f'{att}_acc')] for att in att_list] )
3. 学习率过高导致参数震荡
当前学习率1e-3过大,从验证损失的剧烈波动(如第一个epoch损失73万,第三个epoch骤降到0.7)可看出,模型参数震荡会导致验证集预测结果整体反转,精度跳变到补值。
- 修正方法:降低学习率至
1e-4或1e-5,或使用学习率调度器(如ReduceLROnPlateau)
4. BatchNormalization顺序错误
当前代码中ReLU在BatchNormalization之前,会导致激活后的分布偏移无法被BN纠正,训练稳定性下降。
- 修正方法:调整BN到激活函数之前
def subnet(shared_layers_output, i): att_branch = Dense(512, name='dense_'+str(i)+'_1')(shared_layers_output) att_branch = BatchNormalization()(att_branch) # BN移到ReLU前 att_branch = ReLU()(att_branch) att_branch = Dropout(0.5)(att_branch) att_branch = Dense(512, name='dense_'+str(i)+'_2')(att_branch) att_branch = BatchNormalization()(att_branch) att_branch = ReLU()(att_branch) att_branch = Dropout(0.5)(att_branch) branch_output = Dense(1, name=att_list[i], activation='sigmoid')(att_branch) return branch_output
5. 验证集预处理不一致
检查验证集特征是否与训练集做了相同的预处理(如归一化、标准化),若验证集未做预处理,会导致模型预测完全错误,出现精度异常。
内容的提问来源于stack exchange,提问作者Carlos Daniel Portela
相关产品推荐
相关产品推荐

