编写模型¶
如果您尝试进行全新的任务开发,可能需要从头开始完全实现一个模型。但在许多情况下,您可能更希望对现有模型的某些组件进行修改或扩展。因此,我们也提供了相关机制,允许用户覆盖标准模型中特定内部组件的行为。
注册新组件¶
对于用户经常希望自定义的常见概念,例如“骨干特征提取器”、“边界框头部”,我们提供了一种注册机制,让用户可以注入自定义实现,这些实现将立即可在配置文件中使用。
例如,要添加一个新的主干网络,请在代码中导入以下内容:
from detectron2.modeling import BACKBONE_REGISTRY, Backbone, ShapeSpec
@BACKBONE_REGISTRY.register()
class ToyBackbone(Backbone):
def __init__(self, cfg, input_shape):
super().__init__()
# create your own backbone
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=16, padding=3)
def forward(self, image):
return {"conv1": self.conv1(image)}
def output_shape(self):
return {"conv1": ShapeSpec(channels=64, stride=16)}
在这段代码中,我们按照Backbone类的接口实现了一个新的主干网络,并将其注册到BACKBONE_REGISTRY中,该注册表要求是Backbone的子类。导入这段代码后,detectron2就能将类名与其实现关联起来。因此你可以编写如下代码:
cfg = ... # read a config
cfg.MODEL.BACKBONE.NAME = 'ToyBackbone' # or set it in the config file
model = build_model(cfg) # it will find `ToyBackbone` defined above
再举一个例子,要向广义R-CNN元架构中的ROI头部添加新功能,您可以实现一个新的ROIHeads子类并将其放入ROI_HEADS_REGISTRY中。DensePose和MeshRCNN就是两个实现了新ROIHeads来执行新任务的示例。而projects/目录下还包含了更多实现不同架构的示例。
完整的注册表列表可在API文档中查看。 您可以在这些注册表中注册组件,以自定义模型的不同部分或整个模型。
使用显式参数构建模型¶
Registry(注册表)是连接配置文件中名称与实际代码的桥梁。它们旨在覆盖用户经常需要替换的几个主要组件。然而,基于文本的配置文件功能有时有限,某些更深层次的定制可能只能通过编写代码来实现。
detectron2中的大多数模型组件都有一个清晰的__init__接口,用于记录其所需的输入参数。使用自定义参数调用它们将获得模型的定制变体。
例如,要在Faster R-CNN的边界框头部使用自定义损失函数,我们可以执行以下操作:
损失计算目前是在FastRCNNOutputLayers中进行的。我们需要实现它的一个变体或子类,使用自定义的损失函数,命名为
MyRCNNOutput。使用
box_predictor=MyRCNNOutput()参数调用StandardROIHeads,而非内置的FastRCNNOutputLayers。 若需保持其他参数不变,可通过可配置的__init__机制轻松实现:roi_heads = StandardROIHeads( cfg, backbone.output_shape(), box_predictor=MyRCNNOutput(...) )
(可选)如果我们想通过配置文件启用这个新模型,需要进行注册:
@ROI_HEADS_REGISTRY.register() class MyStandardROIHeads(StandardROIHeads): def __init__(self, cfg, input_shape): super().__init__(cfg, input_shape, box_predictor=MyRCNNOutput(...))