训练后RetinaNet模型predict()仅返回-1值的问题求助
问题分析与解决方案
核心差异定位
model(image_test)返回原始预测张量,而model.predict()会经过Keras CV RetinaNet默认的非极大值抑制(NMS)后处理层。你的情况说明原始预测的置信度极低,被后处理层全部过滤,导致返回空检测结果;而训练时percent_matched_box_with_anchor指标不变,说明模型从一开始就没建立起锚框与标注框的有效匹配,根本没学到有用特征。
可能原因与对应解决方案
1. 后处理层阈值设置过高
Keras CV RetinaNet默认的confidence_threshold可能高于模型输出的所有置信度,导致所有预测被过滤。
- 解决方案:
手动降低后处理层的置信度阈值,可在模型构建时指定,或训练后修改:# 构建模型时显式配置后处理层 post_processing = keras_cv.layers.NonMaxSuppression( confidence_threshold=0.05, # 调低阈值,比如从默认的0.5降到0.05 iou_threshold=0.5, bounding_box_format="xywh" ) model = keras_cv.models.RetinaNet( backbone=backbone, num_classes=2, bounding_box_format="xywh", post_processing=post_processing ) # 若已训练完成,直接修改现有模型的后处理层参数 model.layers[-1].confidence_threshold = 0.05
2. 锚框配置与数据集不匹配
默认锚框的尺度、比例可能不适合船舶目标(比如船舶多为长条形),导致锚框与标注框无法匹配,percent_matched_box_with_anchor指标始终不变。
- 解决方案:
自定义锚框生成器,调整尺度和比例以适配船舶目标:
同时验证标注框格式:确认是anchor_generator = keras_cv.layers.AnchorGenerator( sizes=[32, 64, 128, 256, 512], # 覆盖不同大小的船舶 aspect_ratios=[0.33, 0.5, 1.0, 2.0, 3.0], # 增加长条形比例 bounding_box_format="xywh" ) model = keras_cv.models.RetinaNet( backbone=backbone, num_classes=2, bounding_box_format="xywh", anchor_generator=anchor_generator )xywh格式且坐标范围为0-512(与输入图像尺寸一致),无超出范围的异常值。
3. 训练数据预处理或标注异常
- 检查数据一致性:确保训练时的图像预处理(比如归一化到0-1)与预测时完全一致;若训练用的是归一化坐标,预测时也要对应转换。
- 验证标注质量:打印训练样本的RaggedTensor标注,确认每个样本的boxes和classes对应正确,类别只有0/1,无缺失或错误标注。
4. 冻结Backbone导致特征不足
冻结预训练ResNet50后,固定的ImageNet特征可能无法适配船舶检测任务,加上0.5的dropout,模型难以学习到有效特征。
- 解决方案:
- 解冻Backbone的部分顶层(比如最后10层),或完全解冻:
backbone.trainable = True # 仅解冻最后10层,平衡训练速度与效果 for layer in backbone.layers[:-10]: layer.trainable = False - 降低dropout率至0.2左右,避免过度丢弃特征。
- 解冻Backbone的部分顶层(比如最后10层),或完全解冻:
验证步骤
- 先解决
percent_matched_box_with_anchor不变的问题:训练前手动计算几个样本的锚框匹配情况,确认自定义锚框能与标注框匹配。 - 调整后处理阈值后,用
model.predict()测试,观察是否有有效检测输出。 - 对比训练时的损失曲线:若分类损失始终很高,说明模型未学到类别特征,需检查锚框匹配或数据标注。
内容的提问来源于stack exchange,提问作者Hugo Pires
相关产品推荐
相关产品推荐

