多标签图像分类模型单标签高概率预测问题求解
多标签图像分类模型优化:解决多目标识别时仅输出单一高概率标签的问题
问题背景
基于EfficientNetV2B0构建的多标签图像分类模型,在仅含苹果的单目标图像中预测正常,但在同时包含苹果和香蕉的多目标图像中,仅能输出一个高概率标签。期望模型能为每个标签独立输出0-1之间的概率(无需总和为1),例如:
香蕉 (0.9)
苹果 (0.8)
牛油果 (0.1)
李子 (0.3)
用户实现代码如下:
from efficientnet_v2 import EfficientNetV2B0 def build_model(num_classes=108): base_model = EfficientNetV2B0( input_shape=(224, 224, 3), include_top=False, pooling="avg", weights="imagenet-21k-ft1k" ) base_model.trainable=False return tf.keras.Sequential([ base_model, tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(num_classes, activation='sigmoid') ]) model = build_model() model.summary() model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test), batch_size=32) img = image.load_img('apple-banana.jpg',target_size=(224,224,3)) img = image.img_to_array(img) img = img/255 classes = np.array(train.columns[1:]) proba = model.predict(img.reshape(1,224,224,3)) top_3 = np.argsort(proba[0])[:-6:-1] for i in range(5): print("{}".format(classes[top_3[i]])+" ({:.5})".format(proba[0][top_3[i]])) plt.imshow(img)
解决方案
1. 解冻预训练模型部分层进行微调
当前模型仅训练顶层全连接层,预训练特征不足以捕捉多目标的细粒度特征。解冻模型最后若干层(如20层),结合小学习率微调,既能保留预训练特征,又能让模型学习多目标识别能力:
def build_model(num_classes=108): base_model = EfficientNetV2B0( input_shape=(224, 224, 3), include_top=False, pooling="avg", weights="imagenet-21k-ft1k" ) # 解冻最后20层,冻结前面的层 base_model.trainable = True fine_tune_at = len(base_model.layers) - 20 for layer in base_model.layers[:fine_tune_at]: layer.trainable = False return tf.keras.Sequential([ base_model, tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(num_classes, activation='sigmoid') ]) # 编译时使用小学习率,避免破坏预训练特征 model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-5), loss='binary_crossentropy', metrics=['accuracy'])
2. 优化训练数据与标签
- 补充多目标样本:如果训练集中多目标图像占比低,模型难以学习多目标识别能力,需补充这类样本,或通过数据增强(如随机拼接不同目标图像、翻转/缩放现有多目标图像)提升数据多样性。
- 验证标签格式:确保
y_train和y_test是多标签one-hot编码格式(每个样本标签为长度等于类别数的数组,存在的目标对应位置为1,否则为0),而非单标签分类格式。
3. 替换全局平均池化为全局最大池化
全局平均池化会弱化小目标/边缘目标的特征信号,全局最大池化能更好保留局部强特征,可尝试修改池化方式:
base_model = EfficientNetV2B0( input_shape=(224, 224, 3), include_top=False, pooling="max", # 替换为全局最大池化 weights="imagenet-21k-ft1k" )
进阶方案可采用特征金字塔结构,融合EfficientNet不同阶段的特征,进一步提升多目标识别能力。
4. 调整损失函数与评估指标
- 加入标签平滑,避免模型过度自信:
loss = tf.keras.losses.BinaryCrossentropy(label_smoothing=0.1) model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-5), loss=loss, metrics=['accuracy', tf.keras.metrics.Precision(), tf.keras.metrics.Recall()])
- 用Precision和Recall作为评估指标,更适合多标签任务,能准确反映模型对每个标签的识别性能。
5. 临时后处理调整(快速验证)
可暂时降低预测阈值(如从0.5调整为0.3),查看是否能输出更多高概率标签,但这只是临时方案,核心优化仍需聚焦模型训练环节。
内容的提问来源于stack exchange,提问作者Christian Tan
相关产品推荐
相关产品推荐

