基于Fast R-CNN与VGG16的多类目标检测损失维度不匹配问题求助
问题核心原因
你的错误来自模型输出维度和标签维度不匹配:
你定义的ROI输入roi_input = Input(shape=(None, 4), name="input_2")支持单图传入任意数量的ROI,经过ROI池化、TimeDistributed层处理后,分类头和回归头的输出都会多一个「ROI数量」的维度,输出形状为(batch_size, num_rois, 20)和(batch_size, num_rois, 4)。但你传入的标签形状是(batch_size, 20)和(batch_size, 4),缺少了中间的ROI数量维度,因此损失函数计算时报维度不匹配错误。
对应解决方案
根据你的使用场景二选一即可:
方案1:适配当前单ROI的训练逻辑
你现在每张图只传入1个ROI,直接修改ROI输入的定义,去掉多余的可变维度:
# 把原来的roi_input = Input(shape=(None, 4), name="input_2") 替换为 roi_input = Input(shape=(4,), name="input_2")
修改后ROI池化层的输出不会携带ROI数量维度,最终两个头的输出形状和标签维度完全匹配。
方案2:保留多ROI支持,压缩多余维度
如果你后续需要扩展为单图多ROI训练,在两个输出头的最后添加维度压缩操作即可:
softmaxhead = Dense(20, activation='softmax', kernel_initializer='zero', name='class_label')(softmaxhead) # 加一行压缩ROI维度 softmaxhead = tf.squeeze(softmaxhead, axis=1) bboxhead = Dense(4, activation='sigmoid', name='bounding_box')(bboxhead) # 加一行压缩ROI维度 bboxhead = tf.squeeze(bboxhead, axis=1)
其他需要修正的问题
- ROI坐标预处理:
tf.image.crop_and_resize要求输入的框坐标是归一化到[0,1]区间的相对坐标,如果你传入的是224×224图上的像素坐标,需要先把所有坐标除以224,否则裁剪区域完全错误。 - VGG16输入预处理:你直接传入原始图像没有做VGG16要求的归一化(减去ImageNet数据集均值),会导致预训练权重无法发挥作用,模型收敛速度极慢甚至不收敛。
- 边界框损失选择:平均精度是评估指标,不能作为损失函数使用,边界框回归任务建议使用Smooth L1损失,收敛效果远好于MSE损失。
- 训练逻辑优化:当前每张图仅选1个ROI的训练方式不符合Fast RCNN的设计逻辑,原生Fast RCNN是每张图采样多个正负ROI混合训练,你可以后续修改数据加载逻辑提升检测效果。
内容的提问来源于stack exchange,提问作者Karol E. Mikołajczuk
相关产品推荐
相关产品推荐

