keras-retinanet项目中的RetinaNet模型架构解析
2025-07-08 07:33:59作者:蔡怀权
概述
RetinaNet是一种流行的单阶段目标检测算法,由Facebook AI Research团队提出。本文主要分析keras-retinanet项目中retinanet.py文件的核心实现,该文件包含了RetinaNet模型的主要构建逻辑。
RetinaNet模型架构
RetinaNet模型主要由三部分组成:
- 特征金字塔网络(FPN)
- 分类子网络
- 回归子网络
特征金字塔网络(FPN)
FPN是RetinaNet的核心组件之一,它通过自顶向下和横向连接的方式构建多尺度特征金字塔:
def __create_pyramid_features(backbone_layers, pyramid_levels, feature_size=256):
# 从骨干网络C5层开始构建P5
P5 = keras.layers.Conv2D(feature_size, kernel_size=1, name='C5_reduced')(backbone_layers['C5'])
P5_upsampled = layers.UpsampleLike(name='P5_upsampled')([P5, backbone_layers['C4']])
P5 = keras.layers.Conv2D(feature_size, kernel_size=3, name='P5')(P5)
# 构建P4层
P4 = keras.layers.Conv2D(feature_size, kernel_size=1, name='C4_reduced')(backbone_layers['C4'])
P4 = keras.layers.Add(name='P4_merged')([P5_upsampled, P4])
# 后续类似构建P3,P2等...
FPN通过这种方式构建了P3-P7五个特征层,每个特征层对应不同的感受野,可以检测不同尺度的目标。
分类子网络
分类子网络负责预测每个锚框的类别概率:
def default_classification_model(num_classes, num_anchors, pyramid_feature_size=256):
# 4个3x3卷积层
for i in range(4):
outputs = keras.layers.Conv2D(
filters=classification_feature_size,
activation='relu',
name='pyramid_classification_{}'.format(i),
**options
)(outputs)
# 最后的分类层
outputs = keras.layers.Conv2D(
filters=num_classes * num_anchors,
name='pyramid_classification',
**options
)(outputs)
# 输出处理
outputs = keras.layers.Reshape((-1, num_classes))(outputs)
outputs = keras.layers.Activation('sigmoid')(outputs)
分类子网络采用4个3x3卷积层后接1个1x1卷积层的结构,最后通过sigmoid激活函数输出每个类别的概率。
回归子网络
回归子网络负责预测锚框的偏移量:
def default_regression_model(num_values, num_anchors, pyramid_feature_size=256):
# 4个3x3卷积层
for i in range(4):
outputs = keras.layers.Conv2D(
filters=regression_feature_size,
activation='relu',
name='pyramid_regression_{}'.format(i),
**options
)(outputs)
# 最后的回归层
outputs = keras.layers.Conv2D(num_anchors * num_values, name='pyramid_regression', **options)(outputs)
outputs = keras.layers.Reshape((-1, num_values))(outputs)
回归子网络结构与分类子网络类似,但没有最后的sigmoid激活,直接输出4个坐标偏移量。
模型构建流程
完整的RetinaNet模型构建流程如下:
- 从骨干网络提取特征(C3-C5)
- 构建FPN金字塔特征(P3-P7)
- 在每个金字塔层级应用分类和回归子网络
- 生成锚框
- 将预测结果应用到锚框上
def retinanet(inputs, backbone_layers, num_classes):
# 1. 构建FPN特征金字塔
features = create_pyramid_features(backbone_layers, pyramid_levels)
# 2. 获取各金字塔层级的特征
feature_list = [features['P{}'.format(p)] for p in pyramid_levels]
# 3. 在各层级应用子模型
pyramids = __build_pyramid(submodels, feature_list)
return keras.models.Model(inputs=inputs, outputs=pyramids)
后处理
RetinaNet的后处理包括:
- 将回归预测应用到锚框上得到检测框
- 使用NMS过滤重叠框
- 应用置信度阈值
def retinanet_bbox(model, nms=True, class_specific_filter=True):
# 1. 计算锚框
anchors = __build_anchors(anchor_params, features)
# 2. 应用回归预测
boxes = layers.RegressBoxes()([anchors, regression])
# 3. 过滤检测结果
detections = layers.FilterDetections(
nms=nms,
score_threshold=score_threshold,
max_detections=max_detections
)([boxes, classification])
关键实现细节
- 锚框生成:根据特征图大小和锚框参数动态生成锚框
- 特征金字塔:通过上采样和相加操作构建多尺度特征
- 子网络共享权重:所有金字塔层级共享分类和回归子网络的权重
- 焦点损失:虽然代码中未显示,但RetinaNet使用焦点损失解决类别不平衡问题
总结
keras-retinanet项目的retinanet.py文件实现了RetinaNet的核心架构,包括特征金字塔网络、分类和回归子网络以及后处理流程。通过模块化的设计,可以方便地替换骨干网络或调整模型参数。理解这个实现有助于深入掌握单阶段目标检测算法的核心思想。