Skip to content

builder

model.neck.builder

logger module-attribute

logger = getLogger('SaigeResearch')

FPN

FPN(in_channels: Optional[List[int]] = None, out_channels: int = 64, channel_fpn: int = 256, num_feat: int = 4, num_block: int = 1)

Bases: Module

"Feature Pyramid Networks for Object Detection".

Attributes:

  • block_fpn (ModuleList) –

    torch module list, consists of FpnBlocks.

initializing Feature Pyramid Networks

Parameters:

  • in_channels (List[int], default: None ) –

    channels from backbone network output tensors. Defaults to None.

  • out_channels (int, default: 64 ) –

    final output channels for FPN. Defaults to 64.

  • channel_fpn (int, default: 256 ) –

    inner channels for FpnBlocks. Defaults to 256.

  • num_feat (int, default: 4 ) –

    number of blocks inside of FpnBlocks. Defaults to 4.

  • num_block (int, default: 1 ) –

    number of FpnBlocks. Defaults to 1.

Source code in SaigeToolkit/model/neck/fpn.py
def __init__(
    self,
    in_channels: Optional[List[int]] = None,
    out_channels: int = 64,
    channel_fpn: int = 256,
    num_feat: int = 4,
    num_block: int = 1,
) -> None:
    """initializing Feature Pyramid Networks

    Args:
        in_channels (List[int], optional): channels from backbone network output tensors. Defaults to None.
        out_channels (int, optional): final output channels for FPN. Defaults to 64.
        channel_fpn (int, optional): inner channels for FpnBlocks. Defaults to 256.
        num_feat (int, optional): number of blocks inside of FpnBlocks. Defaults to 4.
        num_block (int, optional): number of FpnBlocks. Defaults to 1.
    """

    super(FPN, self).__init__()

    if in_channels is None:
        in_channels = [64, 128, 256, 512]

    self.block_fpn = []
    for i_nb in range(num_block):
        c_in = in_channels if i_nb == 0 else None
        c_out = out_channels if i_nb == num_block - 1 else None

        self.block_fpn.append(FpnBlock(c_in, c_out, channel_fpn, num_feat))

    self.block_fpn = nn.ModuleList(self.block_fpn)

block_fpn instance-attribute

block_fpn = ModuleList(block_fpn)

forward

forward(features: List[Tensor]) -> List[Tensor]

forward function for FPN

Parameters:

  • features (List[Tensor]) –

    output tensors from backbone network.

Returns:

  • List[Tensor]

    List[torch.Tensor]: output tensors from FPN.

Source code in SaigeToolkit/model/neck/fpn.py
def forward(self, features: List[torch.Tensor]) -> List[torch.Tensor]:
    """forward function for FPN

    Args:
        features (List[torch.Tensor]): output tensors from backbone network.

    Returns:
        List[torch.Tensor]: output tensors from FPN.
    """
    for b_fpn in self.block_fpn:
        features = b_fpn(features)

    return features

FPN_DB

FPN_DB(in_channels: Optional[List[int]] = None, inner_channels: int = 256, bias: bool = False, *args, **kwargs)

Bases: Module

bias: Whether conv layers have bias or not.

Source code in SaigeToolkit/model/neck/fpn.py
def __init__(
    self,
    in_channels: Optional[List[int]] = None,
    inner_channels: int = 256,
    bias: bool = False,
    *args,
    **kwargs,
):
    """
    bias: Whether conv layers have bias or not.
    """
    super(FPN_DB, self).__init__()

    if in_channels is None:
        in_channels = [64, 128, 256, 512]

    self.up5 = nn.Upsample(scale_factor=2, mode="nearest")
    self.up4 = nn.Upsample(scale_factor=2, mode="nearest")
    self.up3 = nn.Upsample(scale_factor=2, mode="nearest")

    self.in5 = nn.Conv2d(in_channels[-1], inner_channels, 1, bias=bias)
    self.in4 = nn.Conv2d(in_channels[-2], inner_channels, 1, bias=bias)
    self.in3 = nn.Conv2d(in_channels[-3], inner_channels, 1, bias=bias)
    self.in2 = nn.Conv2d(in_channels[-4], inner_channels, 1, bias=bias)

    self.out5 = nn.Conv2d(inner_channels, inner_channels // 4, 3, padding=1, bias=bias)
    self.out4 = nn.Conv2d(inner_channels, inner_channels // 4, 3, padding=1, bias=bias)
    self.out3 = nn.Conv2d(inner_channels, inner_channels // 4, 3, padding=1, bias=bias)
    self.out2 = nn.Conv2d(inner_channels, inner_channels // 4, 3, padding=1, bias=bias)

    self.in5.apply(self.weights_init)
    self.in4.apply(self.weights_init)
    self.in3.apply(self.weights_init)
    self.in2.apply(self.weights_init)
    self.out5.apply(self.weights_init)
    self.out4.apply(self.weights_init)
    self.out3.apply(self.weights_init)
    self.out2.apply(self.weights_init)

up5 instance-attribute

up5 = Upsample(scale_factor=2, mode='nearest')

up4 instance-attribute

up4 = Upsample(scale_factor=2, mode='nearest')

up3 instance-attribute

up3 = Upsample(scale_factor=2, mode='nearest')

in5 instance-attribute

in5 = Conv2d(in_channels[-1], inner_channels, 1, bias=bias)

in4 instance-attribute

in4 = Conv2d(in_channels[-2], inner_channels, 1, bias=bias)

in3 instance-attribute

in3 = Conv2d(in_channels[-3], inner_channels, 1, bias=bias)

in2 instance-attribute

in2 = Conv2d(in_channels[-4], inner_channels, 1, bias=bias)

out5 instance-attribute

out5 = Conv2d(inner_channels, inner_channels // 4, 3, padding=1, bias=bias)

out4 instance-attribute

out4 = Conv2d(inner_channels, inner_channels // 4, 3, padding=1, bias=bias)

out3 instance-attribute

out3 = Conv2d(inner_channels, inner_channels // 4, 3, padding=1, bias=bias)

out2 instance-attribute

out2 = Conv2d(inner_channels, inner_channels // 4, 3, padding=1, bias=bias)

weights_init

weights_init(m)
Source code in SaigeToolkit/model/neck/fpn.py
def weights_init(self, m):
    classname = m.__class__.__name__
    if classname.find("Conv") != -1:
        nn.init.kaiming_normal_(m.weight.data)
    elif classname.find("BatchNorm") != -1:
        m.weight.data.fill_(1.0)
        m.bias.data.fill_(1e-4)

forward

forward(features, training=True)
Source code in SaigeToolkit/model/neck/fpn.py
def forward(self, features, training=True):
    c2, c3, c4, c5 = features
    in5 = self.in5(c5)
    in4 = self.in4(c4)
    in3 = self.in3(c3)
    in2 = self.in2(c2)

    out4 = self.up5(in5) + in4  # 1/16
    out3 = self.up4(out4) + in3  # 1/8
    out2 = self.up3(out3) + in2  # 1/4

    p5 = self.out5(in5)
    p4 = self.out4(out4)
    p3 = self.out3(out3)
    p2 = self.out2(out2)

    return p2, p3, p4, p5

BiFPN

BiFPN(in_channels: Optional[List[int]] = None, out_channels: int = 64, channel_fpn: int = 256, num_feat: int = 4, num_block: int = 2)

Bases: Module

"BidirectionalFeaturePyramidNetwork".

Attribute

block_in (nn.ModuleList): list of conv layers, which transfers input channels into fixed channel_fpn block_ex (nn.ModuleList): list of ConvBlock, residual blocks block_fpn (nn.ModuleList): list of BiFpnBlocks block_rtn (nn.ModuleList): list of ConvBlock, refining BiFpnBlock output

initializing Bidirectional FPN

Args:

in_channels (List[int], optional): channels from backbone network output tensors. Defaults to None.
out_channels (int, optional): final output channels for FPN. Defaults to 64.
channel_fpn (int, optional): inner channels for BiFpnBlocks. Defaults to 256.
num_feat (int, optional): number of blocks inside of BiFpnBlocks. Defaults to 4.
num_block (int, optional): number of FpnBlocks. Defaults to 1.
Source code in SaigeToolkit/model/neck/fpn.py
def __init__(
    self,
    in_channels: Optional[List[int]] = None,
    out_channels: int = 64,
    channel_fpn: int = 256,
    num_feat: int = 4,
    num_block: int = 2,
) -> None:
    """initializing Bidirectional FPN

    Args:

        in_channels (List[int], optional): channels from backbone network output tensors. Defaults to None.
        out_channels (int, optional): final output channels for FPN. Defaults to 64.
        channel_fpn (int, optional): inner channels for BiFpnBlocks. Defaults to 256.
        num_feat (int, optional): number of blocks inside of BiFpnBlocks. Defaults to 4.
        num_block (int, optional): number of FpnBlocks. Defaults to 1.
    """

    super(BiFPN, self).__init__()

    if in_channels is None:
        in_channels = [64, 128, 256, 512]
    num_feat = len(in_channels) if num_feat is None else num_feat

    self.block_in = []
    for c in in_channels:
        self.block_in.append(nn.Conv2d(c, channel_fpn, kernel_size=1, stride=1, padding=0))
    self.block_in = nn.ModuleList(self.block_in)

    ex_channels = [in_channels[-1]] + [channel_fpn for _ in range(num_feat - 1 - len(in_channels))]
    ex_channels = ex_channels[: num_feat - len(in_channels)]

    self.block_ex = []
    for c in ex_channels:
        self.block_ex.append(ConvBlock(c, channel_fpn, kernel_size=3, stride=2, padding=1))
    self.block_ex = nn.ModuleList(self.block_ex)

    self.block_fpn = nn.ModuleList([BiFpnBlock(channel_fpn, num_feat) for _ in range(num_block)])

    self.block_rtn = []
    if out_channels != channel_fpn:
        for _ in range(num_feat):
            self.block_rtn.append(
                nn.Conv2d(channel_fpn, out_channels, kernel_size=1, stride=1, padding=0)
            )
    self.block_rtn = nn.ModuleList(self.block_rtn)

block_in instance-attribute

block_in = ModuleList(block_in)

block_ex instance-attribute

block_ex = ModuleList(block_ex)

block_fpn instance-attribute

block_fpn = ModuleList([BiFpnBlock(channel_fpn, num_feat) for _ in range(num_block)])

block_rtn instance-attribute

block_rtn = ModuleList(block_rtn)

forward

forward(inputs: List[Tensor]) -> List[Tensor]

forward function for FPN

Parameters:

  • inputs (List[Tensor]) –

    output tensors from backbone network.

Returns:

  • List[Tensor]

    List[torch.Tensor]: output tensors from BiFPN.

Source code in SaigeToolkit/model/neck/fpn.py
def forward(self, inputs: List[torch.Tensor]) -> List[torch.Tensor]:
    """forward function for FPN

    Args:
        inputs (List[torch.Tensor]): output tensors from backbone network.

    Returns:
        List[torch.Tensor]: output tensors from BiFPN.
    """
    assert len(inputs) == len(self.block_in), "channel number does not fit"

    p_ls = []
    for i_p in range(len(inputs)):
        p_ls.append(self.block_in[i_p](inputs[i_p]))

    if self.block_ex:
        p_ls.append(self.block_ex[0](inputs[-1]))
        for b_ex in self.block_ex[1:]:
            p_ls.append(b_ex(p_ls[-1]))

    for b_fpn in self.block_fpn:
        p_ls = b_fpn(p_ls)

    if self.block_rtn:
        for i_br in range(len(self.block_rtn)):
            p_ls[i_br] = self.block_rtn[i_br](p_ls[i_br])

    return p_ls

FPEM_FFM

FPEM_FFM(backbone_out_channels: Optional[List[int]] = None, **kwargs)

Bases: Module

PANnet :param backbone_out_channels: 基础网络输出的维度

Source code in SaigeToolkit/model/neck/fpem.py
def __init__(self, backbone_out_channels: Optional[List[int]] = None, **kwargs):
    """
    PANnet
    :param backbone_out_channels: 基础网络输出的维度
    """
    super().__init__()
    if backbone_out_channels is None:
        backbone_out_channels = [64, 128, 256, 512]

    fpem_repeat = kwargs.get("fpem_repeat", 2)
    conv_out = 64
    # reduce layers
    self.reduce_conv_c2 = nn.Sequential(
        nn.Conv2d(in_channels=backbone_out_channels[0], out_channels=conv_out, kernel_size=1),
        nn.BatchNorm2d(conv_out),
        nn.ReLU(),
    )
    self.reduce_conv_c3 = nn.Sequential(
        nn.Conv2d(in_channels=backbone_out_channels[1], out_channels=conv_out, kernel_size=1),
        nn.BatchNorm2d(conv_out),
        nn.ReLU(),
    )
    self.reduce_conv_c4 = nn.Sequential(
        nn.Conv2d(in_channels=backbone_out_channels[2], out_channels=conv_out, kernel_size=1),
        nn.BatchNorm2d(conv_out),
        nn.ReLU(),
    )
    self.reduce_conv_c5 = nn.Sequential(
        nn.Conv2d(in_channels=backbone_out_channels[3], out_channels=conv_out, kernel_size=1),
        nn.BatchNorm2d(conv_out),
        nn.ReLU(),
    )
    self.fpems = nn.ModuleList()
    for _ in range(fpem_repeat):
        self.fpems.append(FPEM(conv_out))
    self.out_conv = nn.Conv2d(in_channels=conv_out * 4, out_channels=6, kernel_size=1)

reduce_conv_c2 instance-attribute

reduce_conv_c2 = Sequential(Conv2d(in_channels=backbone_out_channels[0], out_channels=conv_out, kernel_size=1), BatchNorm2d(conv_out), ReLU())

reduce_conv_c3 instance-attribute

reduce_conv_c3 = Sequential(Conv2d(in_channels=backbone_out_channels[1], out_channels=conv_out, kernel_size=1), BatchNorm2d(conv_out), ReLU())

reduce_conv_c4 instance-attribute

reduce_conv_c4 = Sequential(Conv2d(in_channels=backbone_out_channels[2], out_channels=conv_out, kernel_size=1), BatchNorm2d(conv_out), ReLU())

reduce_conv_c5 instance-attribute

reduce_conv_c5 = Sequential(Conv2d(in_channels=backbone_out_channels[3], out_channels=conv_out, kernel_size=1), BatchNorm2d(conv_out), ReLU())

fpems instance-attribute

fpems = ModuleList()

out_conv instance-attribute

out_conv = Conv2d(in_channels=conv_out * 4, out_channels=6, kernel_size=1)

forward

forward(x)
Source code in SaigeToolkit/model/neck/fpem.py
def forward(self, x):
    c2, c3, c4, c5 = x
    # reduce channel
    c2 = self.reduce_conv_c2(c2)
    c3 = self.reduce_conv_c3(c3)
    c4 = self.reduce_conv_c4(c4)
    c5 = self.reduce_conv_c5(c5)

    # FPEM
    for i, fpem in enumerate(self.fpems):
        c2, c3, c4, c5 = fpem(c2, c3, c4, c5)
        if i == 0:
            c2_ffm = c2
            c3_ffm = c3
            c4_ffm = c4
            c5_ffm = c5
        else:
            c2_ffm += c2
            c3_ffm += c3
            c4_ffm += c4
            c5_ffm += c5

    # # FFM
    # c5 = F.interpolate(c5_ffm, c2_ffm.size()[-2:], mode="bilinear")
    # c4 = F.interpolate(c4_ffm, c2_ffm.size()[-2:], mode="bilinear")
    # c3 = F.interpolate(c3_ffm, c2_ffm.size()[-2:], mode="bilinear")
    # Fy = torch.cat([c2_ffm, c3, c4, c5], dim=1)
    # y = self.out_conv(Fy)
    return c2_ffm, c3_ffm, c4_ffm, c5_ffm

build_neck

build_neck(_target_: str, **params) -> Module

build network 'neck' part, such as FPN "Feature Pyramid Networks for Object Detection".

Parameters:

  • cfg_neck (dict) –

    configuration parameters for building 'neck' network

Returns:

  • Module

    nn.Module: 'neck' network

Source code in SaigeToolkit/model/neck/builder.py
def build_neck(_target_: str, **params) -> nn.Module:
    """build network 'neck' part, such as FPN
    ["Feature Pyramid Networks for Object Detection"](https://arxiv.org/abs/1612.03144).

    Args:
        cfg_neck (dict): configuration parameters for building 'neck' network

    Returns:
        nn.Module: 'neck' network

    """
    _types = get_neck_list()
    if _target_ not in _types:
        raise NotImplementedError(f"NECK {_target_} not implemented")
    logger.info(f'[{"NECK".center(9)}] {_target_} [params] {params}')
    return _types[_target_](**params)

get_neck_class

get_neck_class(cfg_neck_name: str) -> Type[Module]

returns neck network class.

Parameters:

  • cfg_neck_name (str) –

    neck network class name

Returns:

  • Type[Module]

    Type[nn.Module]: neck network class

Author

Sukho Yoon

Source code in SaigeToolkit/model/neck/builder.py
def get_neck_class(cfg_neck_name: str) -> Type[nn.Module]:
    """returns neck network class.

    Args:
        cfg_neck_name (str): neck network class name

    Returns:
        Type[nn.Module]: neck network class

    Author:
        Sukho Yoon
    """
    try:
        return get_neck_list()[cfg_neck_name]
    except:
        raise (f"Dataset {cfg_neck_name} not available")

get_neck_list

get_neck_list()
Source code in SaigeToolkit/model/neck/builder.py
def get_neck_list():
    return {
        "db": FPN_DB,
        "fpem": FPEM_FFM,
        "fpn": FPN,
        "bifpn": BiFPN,
    }