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

Keras多标签分类模型准确率偏低的排查与优化咨询

问题背景

我基于Keras搭建了一个多标签图像分类模型,但准确率一直卡在30%-40%,试过多种优化方法都没达到预期效果,想咨询可能的改进方向。

模型实现流程

1. 数据读取与预处理

  • 读取含0/1矩阵的CSV文件:
    df = pd.read_csv(url)
    print(df.head())    
    print(df.columns)
    
  • 读取并调整图像尺寸,归一化后存入X2:
    image_directory = 'Directory/'
    dir_list = os.listdir(path)
    print("Files and directories in '", image_directory, "' :")  
    # print the list
    print(dir_list) 
    
    SIZE = 200
    X_dataset = []
    for i in tqdm(range(df.shape[0])):
        img2 = cv2.imread("Cell{}.png".format(i), cv2.IMREAD_UNCHANGED)
        img = tf.keras.preprocessing.image.load_img(image_directory +df['ID'][i], target_size=(SIZE,SIZE,3))
        #numpy array of each image at size 200, 200, 3 (color)
        img = np.array(img)
        img = img/255.
        X_dataset.append(img)
    
    X2 = np.array(X_dataset)
    print(X2.shape)
    
  • 构建标签数据y2,形状为(1000,16):
    y2 = np.array(df.drop(['Outcome', 'ID'], axis=1))
    print(y2.shape)
    
  • 划分训练集与测试集:
    X_train2, X_test2, y_train2, y_test2 = train_test_split(X2, y2, random_state=10, test_size=0.3)
    

2. 模型构建与编译

  • 搭建CNN模型,包含4个Conv2D层和2个全连接层,输出层用sigmoid激活:
    model2 = Sequential()
    
    model2.add(Conv2D(filters=16, kernel_size=(10, 10), activation="relu", input_shape=(SIZE,SIZE,3)))
    model2.add(BatchNormalization())
    model2.add(MaxPooling2D(pool_size=(5, 5)))
    model2.add(Dropout(0.2))
    
    model2.add(Conv2D(filters=32, kernel_size=(5, 5), activation='relu'))
    model2.add(MaxPooling2D(pool_size=(2, 2)))
    model2.add(BatchNormalization())
    model2.add(Dropout(0.2))
    
    model2.add(Conv2D(filters=64, kernel_size=(5, 5), activation="relu"))
    model2.add(MaxPooling2D(pool_size=(2, 2)))
    model2.add(BatchNormalization())
    model2.add(Dropout(0.2))
    
    model2.add(Conv2D(filters=128, kernel_size=(3, 3), activation='relu'))
    model2.add(MaxPooling2D(pool_size=(2, 2)))
    model2.add(BatchNormalization())
    model2.add(Dropout(0.2))
    
    model2.add(Flatten())
    model2.add(Dense(512, activation='relu'))
    model2.add(Dropout(0.5))
    model2.add(Dense(128, activation='relu'))
    model2.add(Dropout(0.5))
    model2.add(Dense(16, activation='sigmoid'))
    
    #Do not use softmax for multilabel classification
    #Softmax is useful for mutually exclusive classes, either cat or dog but not both.
    #Also, softmax outputs all add to 1. So good for multi class problems where each
    #class is given a probability and all add to 1. Highest one wins. 
    
    #Sigmoid outputs probability. Can be used for non-mutually exclusive problems.
    #like multi label, in this example.
    #But, also good for binary mutually exclusive (cat or not cat). 
    
    model2.summary()
    
  • 使用自定义Adamax优化器,损失函数为binary_crossentropy:
    opt = tf.keras.optimizers.Adamax(
        learning_rate=0.02,
        beta_1=0.8,
        beta_2=0.9999,
        epsilon=1e-9,
        name='Adamax')
    
    model2.compile(optimizer=opt, loss='binary_crossentropy', metrics=['accuracy', 'mse' ])
    

3. 模型训练

  • 设置样本权重(以类别0的样本数为基准计算):
    sample_weight = {     0:1,
                          1:0.5197368421,
                          2:0.4385964912,
                          3:0.2324561404,
                          4:0.2302631579,
                          5:0.399122807,
                          6:0.08114035088,
                          7:0.5723684211,
                          8:0.08552631579,
                          9:0.2061403509,
                          10:0.3815789474,
                          11:0.125,
                          12:0.08333333333,
                          13:0.1206140351,
                          14:0.1403508772,
                          15:0.4824561404
                          }
    
  • 启动训练:
    history = model2.fit(X_train2, y_train2, epochs=25, validation_data=(X_test2, y_test2), batch_size=64, class_weight = sample_weight, shuffle = False)
    
核心问题

模型准确率最高仅30%-40%,部分模型倾向于预测单一类别,效果较好的模型虽有概率分布但表现仍不理想。同时怀疑样本权重设置是否倒置(类别0样本量最大,是不是应该让少数类权重更高)。

已尝试的优化手段
  • 调整batch_size至16或8,训练耗时增加,准确率略有提升;
  • 降低学习率,需要更多epoch才能获得小幅准确率提升;
  • 增加epoch至100,准确率在20轮左右进入平台期;
  • 增加模型参数(如卷积核数量、全连接层神经元数),导致内存占用过高且无明显效果;
  • 更换优化器为Adam、RAdam,效果无显著提升;
  • 清洗CSV数据与图像数据,因担心数据丢失未大量删除。
训练日志示例
14/14 [==============================] - 79s 6s/step - loss: 0.4528 - accuracy: 0.2592 - mse: 0.1594 - val_loss: 261.8521 - val_accuracy: 0.3881 - val_mse: 0.1416
Epoch 2/25
14/14 [==============================] - 85s 6s/step - loss: 0.2817 - accuracy: 0.3188 - mse: 0.1310 - val_loss: 22.7037 - val_accuracy: 0.3881 - val_mse: 0.1416
...
Epoch 13/25
12/14 [========================>.....] - ETA: 10s - loss: 0.2092 - accuracy: 0.3945 - mse: 0.1044

改进建议

1. 修正类别权重设置

你的权重完全搞反了:类别0样本量最大,权重应该最低;少数类样本量少,权重应该更高。正确的计算方式可以用总样本数/(类别样本数×类别总数),或者直接取类别0样本数/目标类别样本数,让少数类权重远大于1,强迫模型重视这些样本。

2. 优化数据预处理

  • 删掉冗余的cv2.imread代码,你只用到了load_img的结果,避免代码混淆。
  • 核对标签有效性:确认每个样本的标签是标准的0/1多热编码,检查是否存在某类标签全0/全1的情况,这类问题会直接导致模型学习偏差。
  • 加入数据增强:用tf.keras.layers.RandomFlip、RandomRotation、RandomZoom等内置层,或者ImageDataGenerator,对训练图像做随机翻转、旋转、亮度调整等操作,扩充数据量,缓解过拟合。

3. 调整模型结构

  • 优化池化策略:第一个MaxPooling用(5,5)太激进,直接把200×200的图像压缩到40×40,丢失大量细节。建议改成(2,2),后续池化也适当缩小步长,保留更多特征。
  • 简化全连接层:512+128的神经元数量对于16类多标签任务冗余度高,容易过拟合。可以改成256+64,或者用GlobalAveragePooling2D替代Flatten,减少参数同时保留全局特征。
  • 尝试迁移学习:用ResNet50、EfficientNetB0等预训练模型做特征提取,冻结底层权重只训练顶层分类层,预训练模型已经学习了通用图像特征,能大幅提升小数据集的效果。

4. 优化训练策略

  • 开启数据打乱:把fit里的shuffle=False改成True,让模型每次epoch都随机读取数据,避免陷入局部最优。
  • 加入学习率调度器:用ReduceLROnPlateau回调,当验证损失不再下降时自动降低学习率,比手动调参更高效。示例代码:
    from tensorflow.keras.callbacks import ReduceLROnPlateau
    lr_scheduler = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, min_lr=1e-5)
    # 在fit中加入callbacks=[lr_scheduler]
    
  • 换用贴合任务的评估指标:多标签任务中普通accuracy意义不大(需所有标签预测正确才算对),改用precision、recall、f1-score或hamming_loss评估,这些指标更能反映模型实际表现,可通过sklearn.metrics计算。

5. 彻底清洗数据

不要怕数据丢失:直接删除标签错误、图像模糊/损坏的样本,这类脏数据会严重干扰模型学习。同时统计各类别样本分布,对样本量极少(如个位数)的类别,要么补充数据,要么暂时剔除,避免模型被极端样本带偏。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 11:25:37