Repository: Project-MONAI/MONAI
File: monai/apps/detection/networks/retinanet_detector.py (Python)

Code before:
    """

    def __init__(
        self,
        network: nn.Module,
        anchor_generator: AnchorGenerator,
        box_overlap_metric: Callable = box_iou,
        spatial_dims: int | None = None,  # used only when network.spatial_dims does not exist
        num_classes: int | None = None,  # used only when network.num_classes does not exist
        num_anchors: int | None = None,  # used only when network.num_anchors does not exist
        size_divisible: Sequence[int] | int = 1,  # used only when network.size_divisible does not exist
        cls_key: str = "classification",  # used only when network.cls_key does not exist
        box_reg_key: str = "box_regression",  # used only when network.box_reg_key does not exist
        debug: bool = False,
    ):
        super().__init__()

        self.network = network
        # network attribute
        self.spatial_dims = self.get_attribute_from_network("spatial_dims", default_value=spatial_dims)
        self.num_classes = self.get_attribute_from_network("num_classes", default_value=num_classes)
        self.size_divisible = self.get_attribute_from_network("size_divisible", default_value=size_divisible)
        self.size_divisible = ensure_tuple_rep(self.size_divisible, self.spatial_dims)
        # keys for the network output
        self.cls_key = self.get_attribute_from_network("cls_key", default_value=cls_key)
        self.box_reg_key = self.get_attribute_from_network("box_reg_key", default_value=box_reg_key)

        # check if anchor_generator matches with network
        self.anchor_generator = anchor_generator

        self.num_anchors_per_loc = self.anchor_generator.num_anchors_per_location()[0]
        if self.num_anchors_per_loc != self.network.num_anchors:
            raise ValueError(
                f"Number of feature map channels ({self.network.num_anchors}) "
                f"should match with number of anchors at each location ({self.num_anchors_per_loc})."
            )
        # if new coming input images has same shape with
        # self.previous_image_shape, there is no need to generate new anchors.
        self.anchors: list[Tensor] | None = None
        self.previous_image_shape: Any | None = None

        self.box_overlap_metric = box_overlap_metric
        self.debug = debug

        # default setting for training
        self.fg_bg_sampler: Any | None = None
        self.set_cls_loss(torch.nn.BCEWithLogitsLoss(reduction="mean"))  # classification loss
        self.set_box_regression_loss(
            torch.nn.SmoothL1Loss(beta=1.0 / 9, reduction="mean"), encode_gt=True, decode_pred=False
        )  # box regression loss


Review comment (suggestion):
Hi @Can-Zhao ,
     I would recommand to add a `self.num_anchors = self.get_attribute_from_network("num_anchors", default_value=num_anchors)` and replace the `self.network.num_anchors` in line 215 with `self.num_anchors`.

Thanks,
Bin

Code after:
    """

    def __init__(
        self,
        network: nn.Module,
        anchor_generator: AnchorGenerator,
        box_overlap_metric: Callable = box_iou,
        spatial_dims: int | None = None,  # used only when network.spatial_dims does not exist
        num_classes: int | None = None,  # used only when network.num_classes does not exist
        size_divisible: Sequence[int] | int = 1,  # used only when network.size_divisible does not exist
        cls_key: str = "classification",  # used only when network.cls_key does not exist
        box_reg_key: str = "box_regression",  # used only when network.box_reg_key does not exist
        debug: bool = False,
    ):
        super().__init__()

        self.network = network
        # network attribute
        self.spatial_dims = self.get_attribute_from_network("spatial_dims", default_value=spatial_dims)
        self.num_classes = self.get_attribute_from_network("num_classes", default_value=num_classes)

        self.size_divisible = self.get_attribute_from_network("size_divisible", default_value=size_divisible)
        self.size_divisible = ensure_tuple_rep(self.size_divisible, self.spatial_dims)
        # keys for the network output
        self.cls_key = self.get_attribute_from_network("cls_key", default_value=cls_key)
        self.box_reg_key = self.get_attribute_from_network("box_reg_key", default_value=box_reg_key)

        # check if anchor_generator matches with network
        self.anchor_generator = anchor_generator
        self.num_anchors_per_loc = self.anchor_generator.num_anchors_per_location()[0]
        network_num_anchors = self.get_attribute_from_network("num_anchors", default_value=self.num_anchors_per_loc)
        if self.num_anchors_per_loc != network_num_anchors:
            raise ValueError(
                f"Number of feature map channels ({network_num_anchors}) "
                f"should match with number of anchors at each location ({self.num_anchors_per_loc})."
            )
        # if new coming input images has same shape with
        # self.previous_image_shape, there is no need to generate new anchors.
        self.anchors: list[Tensor] | None = None
        self.previous_image_shape: Any | None = None

        self.box_overlap_metric = box_overlap_metric
        self.debug = debug

        # default setting for training
        self.fg_bg_sampler: Any | None = None
        self.set_cls_loss(torch.nn.BCEWithLogitsLoss(reduction="mean"))  # classification loss
        self.set_box_regression_loss(
            torch.nn.SmoothL1Loss(beta=1.0 / 9, reduction="mean"), encode_gt=True, decode_pred=False
        )  # box regression loss