You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多任务属性分类模型验证精度异常:固定值或交替补值求助

多任务属性分类模型验证精度异常排查

问题背景

我正在实现一个图像属性分类的多任务学习模型:输入为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 10:16:00