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

基于CNN的带定位图像分类器构建:双分支输出与损失函数配置

构建带定位功能的多输出CNN图像分类器

你这个双分支CNN的思路挺清晰的——在最后一个卷积层后拆分分类和定位任务,分别用二元交叉熵和MSE损失对吧?我帮你把这个方案补全成可运行的代码,顺便把关键细节讲明白:

核心需求回顾

  • 输入:尺寸为(IMG_W, IMG_H, 3)的RGB图像
  • 分类分支:输出二元分类结果,损失用binary crossentropy
  • 定位分支:输出边界框坐标(通常是x, y, w, h四个连续值),损失用mean squared error

完整代码实现

1. 导入依赖库

from tensorflow.keras.layers import Input, Conv2D, Flatten, Dense, Dropout
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam

2. 定义共享卷积骨干网络

这部分是两个分支共用的特征提取层,你可以根据需求增减卷积层数量、调整滤波器参数:

# 先定义图像尺寸(根据你的数据集调整)
IMG_W = 224
IMG_H = 224

# 输入层
input_image = Input(shape=(IMG_W, IMG_H, 3), name='input_image')

# 共享卷积层(延续你给出的示例结构)
x = Conv2D(32, (3,3), strides=(1,1), padding='same', name='conv_1', use_bias=False)(input_image)
x = Conv2D(64, (3,3), strides=(2,2), padding='same', name='conv_2', activation='relu')(x)
x = Conv2D(128, (3,3), strides=(2,2), padding='same', name='conv_3', activation='relu')(x)
# 最后一个共享卷积层
x = Conv2D(256, (3,3), strides=(2,2), padding='same', name='conv_4', activation='relu')(x)

3. 拆分两个任务分支

# -------------------------- 分类分支 --------------------------
classifier_flat = Flatten(name='classifier_flatten')(x)
classifier_dense = Dense(128, activation='relu', name='classifier_dense')(classifier_flat)
classifier_dropout = Dropout(0.5, name='classifier_dropout')(classifier_dense)
# 二元分类用sigmoid激活,输出1个0-1之间的概率值
classification_output = Dense(1, activation='sigmoid', name='classification_output')(classifier_dropout)

# -------------------------- 定位分支 --------------------------
regressor_flat = Flatten(name='regressor_flatten')(x)
regressor_dense = Dense(64, activation='relu', name='regressor_dense')(regressor_flat)
# 定位任务输出连续坐标,用线性激活即可(建议先把坐标归一化到[0,1]区间)
localization_output = Dense(4, activation='linear', name='localization_output')(regressor_dense)

4. 构建多输出模型并编译

关键是为每个分支指定对应的损失函数,还可以通过损失权重调整任务优先级:

# 创建多输出模型
model = Model(inputs=input_image, outputs=[classification_output, localization_output])

# 编译模型:为不同分支配置损失
model.compile(
    optimizer=Adam(learning_rate=1e-4),
    loss={
        'classification_output': 'binary_crossentropy',
        'localization_output': 'mean_squared_error'
    },
    # 可选:调整损失权重,如果定位任务更重要,可以调大对应权重
    loss_weights={
        'classification_output': 1.0,
        'localization_output': 10.0
    },
    # 监控分类分支的准确率指标
    metrics={
        'classification_output': 'accuracy'
    }
)

5. 模型训练

训练时需要传入对应两个分支的标签数据:

# 假设你的训练数据格式:
# X_train: (样本数, IMG_W, IMG_H, 3) 的图像数组
# y_class: (样本数, 1) 的二元分类标签(0或1)
# y_bbox: (样本数, 4) 的归一化边界框坐标

model.fit(
    x=X_train,
    y={
        'classification_output': y_class,
        'localization_output': y_bbox
    },
    batch_size=32,
    epochs=50,
    validation_split=0.2
)

关键细节提示

  • 坐标归一化:建议把边界框的x、y、w、h都除以图像的宽高,归一到[0,1]区间,避免MSE损失数值过大导致训练不稳定
  • 损失权重调整:如果两个任务的损失量级差异大,可以通过loss_weights参数平衡,比如定位任务损失小时调大权重
  • 骨干网络优化:如果需要更好的特征提取能力,可以替换成预训练模型(如MobileNet、ResNet)作为共享骨干

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:07:46