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

Keras多标签分类器准确率无法提升问题排查

基于Keras预训练模型的迁移学习准确率停滞问题

任务背景

基于预训练Keras VGG16模型开展迁移学习,数据集包含10000个样本、14个标签,数据集格式如下:

No finding | Cardiomegaly | ---- | Fracture |
   0.0           0.0                 1.0
   1.0           0.0                 0.1

模型代码实现

(gf为存储0/1格式标签的DataFrame)

train_data, val_data = train_test_split(gf, test_size=0.2)
import tensorflow as tf
datagen=tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255,
                             samplewise_center=True,
                             samplewise_std_normalization=True,
                             rotation_range=40,
                             width_shift_range=0.2,
                             height_shift_range=0.2,
                             shear_range=0.2,
                             zoom_range=0.2,
                             horizontal_flip=True,
                             fill_mode='nearest')

train_flow = datagen.flow_from_dataframe(
    dataframe=train_data,
    directory=image_dir,
    x_col="Path",
    y_col=train_data.columns[5:], # assuming the labels start from the 6th column
    target_size=(224, 224), # assuming you want to resize the images to 224x224
    class_mode="raw",
    batch_size=20,
    shuffle = True,
    seed = 42
)
val_flow = datagen.flow_from_dataframe(
    dataframe=val_data,
    directory=image_dir,
    x_col="Path",
    y_col=val_data.columns[5:], # assuming the labels start from the 6th column
    target_size=(224, 224), # assuming you want to resize the images to 224x224
    class_mode="raw",
    batch_size=20,
    shuffle = True,
    seed = 42
)

base_model = keras.applications.VGG16(
    weights="imagenet",  # Load weights pre-trained on ImageNet.
    input_shape=(224, 224, 3),
    include_top=False,
)  

base_model.trainable = False

inputs = keras.Input(shape=(224, 224, 3))
# We make sure that the base_model is running in inference mode here,
# by passing `training=False`. This is important for fine-tuning, as you will
# learn in a few paragraphs.
x = base_model(inputs, training=False)
# Convert features of shape `base_model.output_shape[1:]` to vectors
x = keras.layers.GlobalAveragePooling2D()(x)
# A Dense classifier with a single unit (binary classification)
outputs = keras.layers.Dense(14, activation='sigmoid')(x)
model = keras.Model(inputs, outputs)

opt = keras.optimizers.Adam(learning_rate=0.001)
model.compile(optimizer=opt, loss='binary_crossentropy', metrics=['accuracy'])

当前问题

模型准确率始终停留在14%左右无法提升,已尝试以下调整均无效:

  • 更换输出层激活函数:sigmoid/softmax
  • 更换损失函数:binary_crossentropy/categorical_crossentropy
  • 调整学习率:0.001/0.0001
  • 更换模型架构:Xception、VGG、MobileNet
  • 将标签从浮点型转为整型

已绘制标签分布柱状图,确认不存在严重标签不平衡问题:
标签分布柱状图


排查与解决方向

1. 数据预处理逻辑修正

  • 预训练模型输入不匹配:VGG16预训练权重基于ImageNet的特定归一化规则(RGB均值为[103.939, 116.779, 123.68],需从像素值中直接减去,无需除以255)。当前同时使用rescale=1./255、samplewise_center和samplewise_std_normalization,会彻底破坏预训练模型的输入特征分布,导致特征提取失效。
    修正代码:
    datagen = tf.keras.preprocessing.image.ImageDataGenerator(
        preprocessing_function=keras.applications.vgg16.preprocess_input,
        rotation_range=40,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True,
        fill_mode='nearest'
    )
    
  • 验证集禁用数据增强:当前验证集和训练集使用相同的数据增强操作,会导致验证指标失真,无法反映模型真实泛化能力。验证集应仅做必要预处理:
    val_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
        preprocessing_function=keras.applications.vgg16.preprocess_input
    )
    val_flow = val_datagen.flow_from_dataframe(
        dataframe=val_data,
        directory=image_dir,
        x_col="Path",
        y_col=val_data.columns[5:],
        target_size=(224, 224),
        class_mode="raw",
        batch_size=20,
        shuffle=False,
        seed=42
    )
    

2. 标签与任务匹配检查

  • 标签格式统一:数据集存在0.1这类非0/1的标签值,多标签分类任务要求标签必须是严格的二值格式(0/1),需将所有大于0的标签值统一设为1,避免模型学习目标混乱。
  • 任务类型对齐:若为多标签任务(样本可同时属于多个类别),sigmoid+binary_crossentropy是正确配置;若为多分类任务(样本仅属于一个类别),则需用softmax+categorical_crossentropy,且标签需转为独热编码,需严格匹配任务类型。

3. 模型训练策略优化

  • 分层解冻微调:当前完全冻结预训练模型,仅训练顶部Dense层,无法提取适配医疗影像任务的特征。建议先训练顶部分类器,再解冻部分顶层预训练层微调:
    # 先训练顶部分类器
    model.fit(train_flow, validation_data=val_flow, epochs=10)
    
    # 解冻VGG16最后4层(共19层)
    base_model.trainable = True
    fine_tune_at = 15
    for layer in base_model.layers[:fine_tune_at]:
        layer.trainable = False
    
    # 微调使用更小的学习率
    model.compile(optimizer=keras.optimizers.Adam(learning_rate=1e-5),
                  loss='binary_crossentropy',
                  metrics=['binary_accuracy'])
    model.fit(train_flow, validation_data=val_flow, epochs=30, initial_epoch=10)
    
  • 更换评估指标:多标签任务中accuracy指标不适用(单个标签错误会影响整体准确率),建议改用binary_accuracy、精准率、召回率等更贴合任务的指标:
    from tensorflow.keras.metrics import Precision, Recall
    
    model.compile(optimizer=opt,
                  loss='binary_crossentropy',
                  metrics=['binary_accuracy', Precision(name='precision'), Recall(name='recall')])
    

4. 数据加载验证

  • 标签列索引确认:打印train_data.columns[5:],确认是否准确指向14个标签列,避免加载错误列作为训练目标。
  • 数据划分一致性:在train_test_split时设置random_state=42,验证集加载时shuffle=False,确保训练/验证集划分无重叠、结果可复现。

内容的提问来源于stack exchange,提问作者Jacob

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 02:38:19