рд╕рд╛рдордЧреНрд░реА рдкрд░ рдЬрд╛рдПрдВ

рдХреЗ рд▓рд┐рдП рд╕рдВрджрд░реНрдн ultralytics/nn/modules/conv.py

рдиреЛрдЯ

рдпрд╣ рдлрд╝рд╛рдЗрд▓ рдпрд╣рд╛рдБ рдЙрдкрд▓рдмреНрдз рд╣реИ https://github.com/ultralytics/ultralytics/рдмреВрдБрдж/рдореБрдЦреНрдп/ultralytics/nn/рдореЙрдбреНрдпреВрд▓/conv.py. рдпрджрд┐ рдЖрдк рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рджреЗрдЦрддреЗ рд╣реИрдВ рддреЛ рдХреГрдкрдпрд╛ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рдХрд╛ рдпреЛрдЧрджрд╛рди рдХрд░рдХреЗ рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдВ ЁЯЫая╕Пред ЁЯЩП рдзрдиреНрдпрд╡рд╛рдж !



ultralytics.nn.modules.conv.Conv

рдХрд╛ рд░реВрдк: Module

рдЖрд░реНрдЧреНрд╕ (ch_in, ch_out, рдХрд░реНрдиреЗрд▓, рд╕реНрдЯреНрд░рд╛рдЗрдб, рдкреИрдбрд┐рдВрдЧ, рд╕рдореВрд╣, рдлреИрд▓рд╛рд╡, рд╕рдХреНрд░рд┐рдпрдг) рдХреЗ рд╕рд╛рде рдорд╛рдирдХ рдХрдирд╡рд▓реНрд╢рдиред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class Conv(nn.Module):
    """Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)."""

    default_act = nn.SiLU()  # default activation

    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
        """Initialize Conv layer with given arguments including activation."""
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()

    def forward(self, x):
        """Apply convolution, batch normalization and activation to input tensor."""
        return self.act(self.bn(self.conv(x)))

    def forward_fuse(self, x):
        """Perform transposed convolution of 2D data."""
        return self.act(self.conv(x))

__init__(c1, c2, k=1, s=1, p=None, g=1, d=1, act=True)

рд╕рдХреНрд░рд┐рдпрдг рд╕рд╣рд┐рдд рджрд┐рдП рдЧрдП рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде Conv рдкрд░рдд рдХреЛ рдкреНрд░рд╛рд░рдВрдн рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
    """Initialize Conv layer with given arguments including activation."""
    super().__init__()
    self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
    self.bn = nn.BatchNorm2d(c2)
    self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()

forward(x)

рдЗрдирдкреБрдЯ рдХреЗ рд▓рд┐рдП рдХрдирд╡рд▓реНрд╢рди, рдмреИрдЪ рд╕рд╛рдорд╛рдиреНрдпреАрдХрд░рдг рдФрд░ рд╕рдХреНрд░рд┐рдпрдг рд▓рд╛рдЧреВ рдХрд░реЗрдВ tensor.

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward(self, x):
    """Apply convolution, batch normalization and activation to input tensor."""
    return self.act(self.bn(self.conv(x)))

forward_fuse(x)

2D рдбреЗрдЯрд╛ рдХрд╛ рдЯреНрд░рд╛рдВрд╕рдкреЛрдЬрд╝реНрдб рдХрдирд╡рд▓реНрд╢рди рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward_fuse(self, x):
    """Perform transposed convolution of 2D data."""
    return self.act(self.conv(x))



ultralytics.nn.modules.conv.Conv2

рдХрд╛ рд░реВрдк: Conv

рдХрдиреНрд╡ рдлреНрдпреВрдЬрд╝рд┐рдВрдЧ рдХреЗ рд╕рд╛рде рд╕рд░рд▓реАрдХреГрдд RepConv рдореЙрдбреНрдпреВрд▓ред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class Conv2(Conv):
    """Simplified RepConv module with Conv fusing."""

    def __init__(self, c1, c2, k=3, s=1, p=None, g=1, d=1, act=True):
        """Initialize Conv layer with given arguments including activation."""
        super().__init__(c1, c2, k, s, p, g=g, d=d, act=act)
        self.cv2 = nn.Conv2d(c1, c2, 1, s, autopad(1, p, d), groups=g, dilation=d, bias=False)  # add 1x1 conv

    def forward(self, x):
        """Apply convolution, batch normalization and activation to input tensor."""
        return self.act(self.bn(self.conv(x) + self.cv2(x)))

    def forward_fuse(self, x):
        """Apply fused convolution, batch normalization and activation to input tensor."""
        return self.act(self.bn(self.conv(x)))

    def fuse_convs(self):
        """Fuse parallel convolutions."""
        w = torch.zeros_like(self.conv.weight.data)
        i = [x // 2 for x in w.shape[2:]]
        w[:, :, i[0] : i[0] + 1, i[1] : i[1] + 1] = self.cv2.weight.data.clone()
        self.conv.weight.data += w
        self.__delattr__("cv2")
        self.forward = self.forward_fuse

__init__(c1, c2, k=3, s=1, p=None, g=1, d=1, act=True)

рд╕рдХреНрд░рд┐рдпрдг рд╕рд╣рд┐рдд рджрд┐рдП рдЧрдП рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде Conv рдкрд░рдд рдХреЛ рдкреНрд░рд╛рд░рдВрдн рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, c1, c2, k=3, s=1, p=None, g=1, d=1, act=True):
    """Initialize Conv layer with given arguments including activation."""
    super().__init__(c1, c2, k, s, p, g=g, d=d, act=act)
    self.cv2 = nn.Conv2d(c1, c2, 1, s, autopad(1, p, d), groups=g, dilation=d, bias=False)  # add 1x1 conv

forward(x)

рдЗрдирдкреБрдЯ рдХреЗ рд▓рд┐рдП рдХрдирд╡рд▓реНрд╢рди, рдмреИрдЪ рд╕рд╛рдорд╛рдиреНрдпреАрдХрд░рдг рдФрд░ рд╕рдХреНрд░рд┐рдпрдг рд▓рд╛рдЧреВ рдХрд░реЗрдВ tensor.

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward(self, x):
    """Apply convolution, batch normalization and activation to input tensor."""
    return self.act(self.bn(self.conv(x) + self.cv2(x)))

forward_fuse(x)

рдЗрдирдкреБрдЯ рдХреЗ рд▓рд┐рдП рдлреНрдпреВрдЬреНрдб рдХрдирд╡рд▓реНрд╢рди, рдмреИрдЪ рд╕рд╛рдорд╛рдиреНрдпреАрдХрд░рдг рдФрд░ рд╕рдХреНрд░рд┐рдпрдг рд▓рд╛рдЧреВ рдХрд░реЗрдВ tensor.

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward_fuse(self, x):
    """Apply fused convolution, batch normalization and activation to input tensor."""
    return self.act(self.bn(self.conv(x)))

fuse_convs()

рд╕рдорд╛рдирд╛рдВрддрд░ convolutions рдлреНрдпреВрдЬред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def fuse_convs(self):
    """Fuse parallel convolutions."""
    w = torch.zeros_like(self.conv.weight.data)
    i = [x // 2 for x in w.shape[2:]]
    w[:, :, i[0] : i[0] + 1, i[1] : i[1] + 1] = self.cv2.weight.data.clone()
    self.conv.weight.data += w
    self.__delattr__("cv2")
    self.forward = self.forward_fuse



ultralytics.nn.modules.conv.LightConv

рдХрд╛ рд░реВрдк: Module

рдЖрд░реНрдЧреНрд╕ (ch_in, ch_out, рдХрд░реНрдиреЗрд▓) рдХреЗ рд╕рд╛рде рдкреНрд░рдХрд╛рд╢ рдХрдирд╡рд▓реНрд╢рдиред

https://github.com/PaddlePaddle/PaddleDetection/blob/develop/ppdet/modeling/backbones/hgnet_v2.py

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class LightConv(nn.Module):
    """
    Light convolution with args(ch_in, ch_out, kernel).

    https://github.com/PaddlePaddle/PaddleDetection/blob/develop/ppdet/modeling/backbones/hgnet_v2.py
    """

    def __init__(self, c1, c2, k=1, act=nn.ReLU()):
        """Initialize Conv layer with given arguments including activation."""
        super().__init__()
        self.conv1 = Conv(c1, c2, 1, act=False)
        self.conv2 = DWConv(c2, c2, k, act=act)

    def forward(self, x):
        """Apply 2 convolutions to input tensor."""
        return self.conv2(self.conv1(x))

__init__(c1, c2, k=1, act=nn.ReLU())

рд╕рдХреНрд░рд┐рдпрдг рд╕рд╣рд┐рдд рджрд┐рдП рдЧрдП рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде Conv рдкрд░рдд рдХреЛ рдкреНрд░рд╛рд░рдВрдн рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, c1, c2, k=1, act=nn.ReLU()):
    """Initialize Conv layer with given arguments including activation."""
    super().__init__()
    self.conv1 = Conv(c1, c2, 1, act=False)
    self.conv2 = DWConv(c2, c2, k, act=act)

forward(x)

рдЗрдирдкреБрдЯ рдХреЗ рд▓рд┐рдП 2 convolutions рд▓рд╛рдЧреВ рдХрд░реЗрдВ tensor.

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward(self, x):
    """Apply 2 convolutions to input tensor."""
    return self.conv2(self.conv1(x))



ultralytics.nn.modules.conv.DWConv

рдХрд╛ рд░реВрдк: Conv

рдЧрд╣рд░рд╛рдИ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХрдирд╡рд▓реНрд╢рдиред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class DWConv(Conv):
    """Depth-wise convolution."""

    def __init__(self, c1, c2, k=1, s=1, d=1, act=True):  # ch_in, ch_out, kernel, stride, dilation, activation
        """Initialize Depth-wise convolution with given parameters."""
        super().__init__(c1, c2, k, s, g=math.gcd(c1, c2), d=d, act=act)

__init__(c1, c2, k=1, s=1, d=1, act=True)

рджрд┐рдП рдЧрдП рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдЧрд╣рд░рд╛рдИ-рд╡рд╛рд░ рдХрдирд╡рд▓реНрд╢рди рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, c1, c2, k=1, s=1, d=1, act=True):  # ch_in, ch_out, kernel, stride, dilation, activation
    """Initialize Depth-wise convolution with given parameters."""
    super().__init__(c1, c2, k, s, g=math.gcd(c1, c2), d=d, act=act)



ultralytics.nn.modules.conv.DWConvTranspose2d

рдХрд╛ рд░реВрдк: ConvTranspose2d

рдЧрд╣рд░рд╛рдИ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХрдиреНрд╡рд▓реНрд╢рди рдЯреНрд░рд╛рдВрд╕рдкреЛрдЬ рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class DWConvTranspose2d(nn.ConvTranspose2d):
    """Depth-wise transpose convolution."""

    def __init__(self, c1, c2, k=1, s=1, p1=0, p2=0):  # ch_in, ch_out, kernel, stride, padding, padding_out
        """Initialize DWConvTranspose2d class with given parameters."""
        super().__init__(c1, c2, k, s, p1, p2, groups=math.gcd(c1, c2))

__init__(c1, c2, k=1, s=1, p1=0, p2=0)

рджрд┐рдП рдЧрдП рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде DWConvTranspose2d рдХреНрд▓рд╛рд╕ рдкреНрд░рд╛рд░рдВрдн рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, c1, c2, k=1, s=1, p1=0, p2=0):  # ch_in, ch_out, kernel, stride, padding, padding_out
    """Initialize DWConvTranspose2d class with given parameters."""
    super().__init__(c1, c2, k, s, p1, p2, groups=math.gcd(c1, c2))



ultralytics.nn.modules.conv.ConvTranspose

рдХрд╛ рд░реВрдк: Module

рдХрдирд╡рд▓реНрд╢рди 2d рдкрд░рдд рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class ConvTranspose(nn.Module):
    """Convolution transpose 2d layer."""

    default_act = nn.SiLU()  # default activation

    def __init__(self, c1, c2, k=2, s=2, p=0, bn=True, act=True):
        """Initialize ConvTranspose2d layer with batch normalization and activation function."""
        super().__init__()
        self.conv_transpose = nn.ConvTranspose2d(c1, c2, k, s, p, bias=not bn)
        self.bn = nn.BatchNorm2d(c2) if bn else nn.Identity()
        self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()

    def forward(self, x):
        """Applies transposed convolutions, batch normalization and activation to input."""
        return self.act(self.bn(self.conv_transpose(x)))

    def forward_fuse(self, x):
        """Applies activation and convolution transpose operation to input."""
        return self.act(self.conv_transpose(x))

__init__(c1, c2, k=2, s=2, p=0, bn=True, act=True)

рдмреИрдЪ рд╕рд╛рдорд╛рдиреНрдпреАрдХрд░рдг рдФрд░ рд╕рдХреНрд░рд┐рдпрдг рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде ConvTranspose2d рдкрд░рдд рдкреНрд░рд╛рд░рдВрдн рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, c1, c2, k=2, s=2, p=0, bn=True, act=True):
    """Initialize ConvTranspose2d layer with batch normalization and activation function."""
    super().__init__()
    self.conv_transpose = nn.ConvTranspose2d(c1, c2, k, s, p, bias=not bn)
    self.bn = nn.BatchNorm2d(c2) if bn else nn.Identity()
    self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()

forward(x)

рдЗрдирдкреБрдЯ рдХреЗ рд▓рд┐рдП рдЯреНрд░рд╛рдВрд╕рдкреЛрдЬрд╝реНрдб convolutions, рдмреИрдЪ рд╕рд╛рдорд╛рдиреНрдпреАрдХрд░рдг рдФрд░ рд╕рдХреНрд░рд┐рдпрдг рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward(self, x):
    """Applies transposed convolutions, batch normalization and activation to input."""
    return self.act(self.bn(self.conv_transpose(x)))

forward_fuse(x)

рдЗрдирдкреБрдЯ рдХреЗ рд▓рд┐рдП рд╕рдХреНрд░рд┐рдпрдг рдФрд░ рдХрдирд╡рд▓реНрд╢рди рдЯреНрд░рд╛рдВрд╕рдкреЛрдЬрд╝ рдСрдкрд░реЗрд╢рди рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward_fuse(self, x):
    """Applies activation and convolution transpose operation to input."""
    return self.act(self.conv_transpose(x))



ultralytics.nn.modules.conv.Focus

рдХрд╛ рд░реВрдк: Module

рд╕реА-рд╕реНрдкреЗрд╕ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдкрд░ рдзреНрдпрд╛рди рджреЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class Focus(nn.Module):
    """Focus wh information into c-space."""

    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):
        """Initializes Focus object with user defined channel, convolution, padding, group and activation values."""
        super().__init__()
        self.conv = Conv(c1 * 4, c2, k, s, p, g, act=act)
        # self.contract = Contract(gain=2)

    def forward(self, x):
        """
        Applies convolution to concatenated tensor and returns the output.

        Input shape is (b,c,w,h) and output shape is (b,4c,w/2,h/2).
        """
        return self.conv(torch.cat((x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]), 1))

__init__(c1, c2, k=1, s=1, p=None, g=1, act=True)

рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдЪреИрдирд▓, рдХрдирд╡рд▓реНрд╢рди, рдкреИрдбрд┐рдВрдЧ, рд╕рдореВрд╣ рдФрд░ рд╕рдХреНрд░рд┐рдпрдг рдорд╛рдиреЛрдВ рдХреЗ рд╕рд╛рде рдлреЛрдХрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):
    """Initializes Focus object with user defined channel, convolution, padding, group and activation values."""
    super().__init__()
    self.conv = Conv(c1 * 4, c2, k, s, p, g, act=act)

forward(x)

concatenated рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдирд╡рд▓реНрд╢рди рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ tensor рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рд▓реМрдЯрд╛рддрд╛ рд╣реИред

рдЗрдирдкреБрдЯ рдЖрдХрд╛рд░ (рдмреА, рд╕реА, рдбрдмреНрд▓реНрдпреВ, рдПрдЪ) рд╣реИ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдЖрдХрд╛рд░ (рдмреА, 4 рд╕реА, рдбрдмреНрд▓реНрдпреВ / 2, рдПрдЪ / 2) рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward(self, x):
    """
    Applies convolution to concatenated tensor and returns the output.

    Input shape is (b,c,w,h) and output shape is (b,4c,w/2,h/2).
    """
    return self.conv(torch.cat((x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]), 1))



ultralytics.nn.modules.conv.GhostConv

рдХрд╛ рд░реВрдк: Module

рднреВрдд рдХрдирд╡рд▓реНрд╢рди https://github.com/huawei-noah/ghostnetред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class GhostConv(nn.Module):
    """Ghost Convolution https://github.com/huawei-noah/ghostnet."""

    def __init__(self, c1, c2, k=1, s=1, g=1, act=True):
        """Initializes the GhostConv object with input channels, output channels, kernel size, stride, groups and
        activation.
        """
        super().__init__()
        c_ = c2 // 2  # hidden channels
        self.cv1 = Conv(c1, c_, k, s, None, g, act=act)
        self.cv2 = Conv(c_, c_, 5, 1, None, c_, act=act)

    def forward(self, x):
        """Forward propagation through a Ghost Bottleneck layer with skip connection."""
        y = self.cv1(x)
        return torch.cat((y, self.cv2(y)), 1)

__init__(c1, c2, k=1, s=1, g=1, act=True)

GhostConv рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдЗрдирдкреБрдЯ рдЪреИрдирд▓, рдЖрдЙрдЯрдкреБрдЯ рдЪреИрдирд▓, рдХрд░реНрдиреЗрд▓ рдЖрдХрд╛рд░, рд╕реНрдЯреНрд░рд╛рдЗрдб, рд╕рдореВрд╣ рдФрд░ рд╕рдХреНрд░рд┐рдпрдгред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, c1, c2, k=1, s=1, g=1, act=True):
    """Initializes the GhostConv object with input channels, output channels, kernel size, stride, groups and
    activation.
    """
    super().__init__()
    c_ = c2 // 2  # hidden channels
    self.cv1 = Conv(c1, c_, k, s, None, g, act=act)
    self.cv2 = Conv(c_, c_, 5, 1, None, c_, act=act)

forward(x)

рд╕реНрдХрд┐рдк рдХрдиреЗрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдШреЛрд╕реНрдЯ рдмреЙрдЯрд▓рдиреЗрдХ рд▓реЗрдпрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдлреЙрд░рд╡рд░реНрдб рдкреНрд░рд╕рд╛рд░ред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward(self, x):
    """Forward propagation through a Ghost Bottleneck layer with skip connection."""
    y = self.cv1(x)
    return torch.cat((y, self.cv2(y)), 1)



ultralytics.nn.modules.conv.RepConv

рдХрд╛ рд░реВрдк: Module

RepConv рдПрдХ рдмреБрдирд┐рдпрд╛рджреА рдкреНрд░рддрд┐рдирд┐рдзрд┐-рд╢реИрд▓реА рдмреНрд▓реЙрдХ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдФрд░ рддреИрдирд╛рддреА рдХреА рд╕реНрдерд┐рддрд┐ рд╢рд╛рдорд┐рд▓ рд╣реИред

рдЗрд╕ рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ RT-DETR. https://github.com/DingXiaoH/RepVGG/blob/main/repvgg.py рдЖрдзрд╛рд░ рдкрд░

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class RepConv(nn.Module):
    """
    RepConv is a basic rep-style block, including training and deploy status.

    This module is used in RT-DETR.
    Based on https://github.com/DingXiaoH/RepVGG/blob/main/repvgg.py
    """

    default_act = nn.SiLU()  # default activation

    def __init__(self, c1, c2, k=3, s=1, p=1, g=1, d=1, act=True, bn=False, deploy=False):
        """Initializes Light Convolution layer with inputs, outputs & optional activation function."""
        super().__init__()
        assert k == 3 and p == 1
        self.g = g
        self.c1 = c1
        self.c2 = c2
        self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()

        self.bn = nn.BatchNorm2d(num_features=c1) if bn and c2 == c1 and s == 1 else None
        self.conv1 = Conv(c1, c2, k, s, p=p, g=g, act=False)
        self.conv2 = Conv(c1, c2, 1, s, p=(p - k // 2), g=g, act=False)

    def forward_fuse(self, x):
        """Forward process."""
        return self.act(self.conv(x))

    def forward(self, x):
        """Forward process."""
        id_out = 0 if self.bn is None else self.bn(x)
        return self.act(self.conv1(x) + self.conv2(x) + id_out)

    def get_equivalent_kernel_bias(self):
        """Returns equivalent kernel and bias by adding 3x3 kernel, 1x1 kernel and identity kernel with their biases."""
        kernel3x3, bias3x3 = self._fuse_bn_tensor(self.conv1)
        kernel1x1, bias1x1 = self._fuse_bn_tensor(self.conv2)
        kernelid, biasid = self._fuse_bn_tensor(self.bn)
        return kernel3x3 + self._pad_1x1_to_3x3_tensor(kernel1x1) + kernelid, bias3x3 + bias1x1 + biasid

    def _pad_1x1_to_3x3_tensor(self, kernel1x1):
        """Pads a 1x1 tensor to a 3x3 tensor."""
        if kernel1x1 is None:
            return 0
        else:
            return torch.nn.functional.pad(kernel1x1, [1, 1, 1, 1])

    def _fuse_bn_tensor(self, branch):
        """Generates appropriate kernels and biases for convolution by fusing branches of the neural network."""
        if branch is None:
            return 0, 0
        if isinstance(branch, Conv):
            kernel = branch.conv.weight
            running_mean = branch.bn.running_mean
            running_var = branch.bn.running_var
            gamma = branch.bn.weight
            beta = branch.bn.bias
            eps = branch.bn.eps
        elif isinstance(branch, nn.BatchNorm2d):
            if not hasattr(self, "id_tensor"):
                input_dim = self.c1 // self.g
                kernel_value = np.zeros((self.c1, input_dim, 3, 3), dtype=np.float32)
                for i in range(self.c1):
                    kernel_value[i, i % input_dim, 1, 1] = 1
                self.id_tensor = torch.from_numpy(kernel_value).to(branch.weight.device)
            kernel = self.id_tensor
            running_mean = branch.running_mean
            running_var = branch.running_var
            gamma = branch.weight
            beta = branch.bias
            eps = branch.eps
        std = (running_var + eps).sqrt()
        t = (gamma / std).reshape(-1, 1, 1, 1)
        return kernel * t, beta - running_mean * gamma / std

    def fuse_convs(self):
        """Combines two convolution layers into a single layer and removes unused attributes from the class."""
        if hasattr(self, "conv"):
            return
        kernel, bias = self.get_equivalent_kernel_bias()
        self.conv = nn.Conv2d(
            in_channels=self.conv1.conv.in_channels,
            out_channels=self.conv1.conv.out_channels,
            kernel_size=self.conv1.conv.kernel_size,
            stride=self.conv1.conv.stride,
            padding=self.conv1.conv.padding,
            dilation=self.conv1.conv.dilation,
            groups=self.conv1.conv.groups,
            bias=True,
        ).requires_grad_(False)
        self.conv.weight.data = kernel
        self.conv.bias.data = bias
        for para in self.parameters():
            para.detach_()
        self.__delattr__("conv1")
        self.__delattr__("conv2")
        if hasattr(self, "nm"):
            self.__delattr__("nm")
        if hasattr(self, "bn"):
            self.__delattr__("bn")
        if hasattr(self, "id_tensor"):
            self.__delattr__("id_tensor")

__init__(c1, c2, k=3, s=1, p=1, g=1, d=1, act=True, bn=False, deploy=False)

рдЗрдирдкреБрдЯ, рдЖрдЙрдЯрдкреБрдЯ рдФрд░ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╕рдХреНрд░рд┐рдпрдг рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рд▓рд╛рдЗрдЯ рдХрдирд╡рд▓реНрд╢рди рд▓реЗрдпрд░ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, c1, c2, k=3, s=1, p=1, g=1, d=1, act=True, bn=False, deploy=False):
    """Initializes Light Convolution layer with inputs, outputs & optional activation function."""
    super().__init__()
    assert k == 3 and p == 1
    self.g = g
    self.c1 = c1
    self.c2 = c2
    self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()

    self.bn = nn.BatchNorm2d(num_features=c1) if bn and c2 == c1 and s == 1 else None
    self.conv1 = Conv(c1, c2, k, s, p=p, g=g, act=False)
    self.conv2 = Conv(c1, c2, 1, s, p=(p - k // 2), g=g, act=False)

forward(x)

рдЖрдЧреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward(self, x):
    """Forward process."""
    id_out = 0 if self.bn is None else self.bn(x)
    return self.act(self.conv1(x) + self.conv2(x) + id_out)

forward_fuse(x)

рдЖрдЧреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward_fuse(self, x):
    """Forward process."""
    return self.act(self.conv(x))

fuse_convs()

рджреЛ рдХрдирд╡рд▓реНрд╢рди рдкрд░рддреЛрдВ рдХреЛ рдПрдХ рдкрд░рдд рдореЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИ рдФрд░ рдХрдХреНрд╖рд╛ рд╕реЗ рдЕрдкреНрд░рдпреБрдХреНрдд рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рд╣рдЯрд╛ рджреЗрддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def fuse_convs(self):
    """Combines two convolution layers into a single layer and removes unused attributes from the class."""
    if hasattr(self, "conv"):
        return
    kernel, bias = self.get_equivalent_kernel_bias()
    self.conv = nn.Conv2d(
        in_channels=self.conv1.conv.in_channels,
        out_channels=self.conv1.conv.out_channels,
        kernel_size=self.conv1.conv.kernel_size,
        stride=self.conv1.conv.stride,
        padding=self.conv1.conv.padding,
        dilation=self.conv1.conv.dilation,
        groups=self.conv1.conv.groups,
        bias=True,
    ).requires_grad_(False)
    self.conv.weight.data = kernel
    self.conv.bias.data = bias
    for para in self.parameters():
        para.detach_()
    self.__delattr__("conv1")
    self.__delattr__("conv2")
    if hasattr(self, "nm"):
        self.__delattr__("nm")
    if hasattr(self, "bn"):
        self.__delattr__("bn")
    if hasattr(self, "id_tensor"):
        self.__delattr__("id_tensor")

get_equivalent_kernel_bias()

рд╕рдорддреБрд▓реНрдп рдХрд░реНрдиреЗрд▓ рдФрд░ рдмрд╛рдпрд╕ рдХреЛ рдЙрдирдХреЗ рдкреВрд░реНрд╡рд╛рдЧреНрд░рд╣реЛрдВ рдХреЗ рд╕рд╛рде 3x3 рдХрд░реНрдиреЗрд▓, 1x1 рдХрд░реНрдиреЗрд▓ рдФрд░ рдкрд╣рдЪрд╛рди рдХрд░реНрдиреЗрд▓ рдЬреЛрдбрд╝рдХрд░ рд▓реМрдЯрд╛рддрд╛ рд╣реИ.

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def get_equivalent_kernel_bias(self):
    """Returns equivalent kernel and bias by adding 3x3 kernel, 1x1 kernel and identity kernel with their biases."""
    kernel3x3, bias3x3 = self._fuse_bn_tensor(self.conv1)
    kernel1x1, bias1x1 = self._fuse_bn_tensor(self.conv2)
    kernelid, biasid = self._fuse_bn_tensor(self.bn)
    return kernel3x3 + self._pad_1x1_to_3x3_tensor(kernel1x1) + kernelid, bias3x3 + bias1x1 + biasid



ultralytics.nn.modules.conv.ChannelAttention

рдХрд╛ рд░реВрдк: Module

рдЪреИрдирд▓-рдзреНрдпрд╛рди рдореЙрдбреНрдпреВрд▓ https://github.com/open-mmlab/mmdetection/tree/v3.0.0rc1/configs/rtmdetред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class ChannelAttention(nn.Module):
    """Channel-attention module https://github.com/open-mmlab/mmdetection/tree/v3.0.0rc1/configs/rtmdet."""

    def __init__(self, channels: int) -> None:
        """Initializes the class and sets the basic configurations and instance variables required."""
        super().__init__()
        self.pool = nn.AdaptiveAvgPool2d(1)
        self.fc = nn.Conv2d(channels, channels, 1, 1, 0, bias=True)
        self.act = nn.Sigmoid()

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        """Applies forward pass using activation on convolutions of the input, optionally using batch normalization."""
        return x * self.act(self.fc(self.pool(x)))

__init__(channels)

рдХреНрд▓рд╛рд╕ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЖрд╡рд╢реНрдпрдХ рдмреЗрд╕рд┐рдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдФрд░ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рд╡реИрд░рд┐рдПрдмрд▓ рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, channels: int) -> None:
    """Initializes the class and sets the basic configurations and instance variables required."""
    super().__init__()
    self.pool = nn.AdaptiveAvgPool2d(1)
    self.fc = nn.Conv2d(channels, channels, 1, 1, 0, bias=True)
    self.act = nn.Sigmoid()

forward(x)

рдЗрдирдкреБрдЯ рдХреЗ рдХрдирд╡рд▓реНрд╢рди рдкрд░ рд╕рдХреНрд░рд┐рдпрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдлреЙрд░рд╡рд░реНрдб рдкрд╛рд╕ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ рдмреИрдЪ рд╕рд╛рдорд╛рдиреНрдпреАрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward(self, x: torch.Tensor) -> torch.Tensor:
    """Applies forward pass using activation on convolutions of the input, optionally using batch normalization."""
    return x * self.act(self.fc(self.pool(x)))



ultralytics.nn.modules.conv.SpatialAttention

рдХрд╛ рд░реВрдк: Module

рд╕реНрдерд╛рдирд┐рдХ-рдзреНрдпрд╛рди рдореЙрдбреНрдпреВрд▓ред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class SpatialAttention(nn.Module):
    """Spatial-attention module."""

    def __init__(self, kernel_size=7):
        """Initialize Spatial-attention module with kernel size argument."""
        super().__init__()
        assert kernel_size in {3, 7}, "kernel size must be 3 or 7"
        padding = 3 if kernel_size == 7 else 1
        self.cv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
        self.act = nn.Sigmoid()

    def forward(self, x):
        """Apply channel and spatial attention on input for feature recalibration."""
        return x * self.act(self.cv1(torch.cat([torch.mean(x, 1, keepdim=True), torch.max(x, 1, keepdim=True)[0]], 1)))

__init__(kernel_size=7)

рдХрд░реНрдиреЗрд▓ рдЖрдХрд╛рд░ рддрд░реНрдХ рдХреЗ рд╕рд╛рде рд╕реНрдерд╛рдирд┐рдХ-рдзреНрдпрд╛рди рдореЙрдбреНрдпреВрд▓ рдкреНрд░рд╛рд░рдВрдн рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, kernel_size=7):
    """Initialize Spatial-attention module with kernel size argument."""
    super().__init__()
    assert kernel_size in {3, 7}, "kernel size must be 3 or 7"
    padding = 3 if kernel_size == 7 else 1
    self.cv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
    self.act = nn.Sigmoid()

forward(x)

рд╕реБрд╡рд┐рдзрд╛ рдкреБрдирд░реНрдЧрдгрдирд╛ рдХреЗ рд▓рд┐рдП рдЗрдирдкреБрдЯ рдкрд░ рдЪреИрдирд▓ рдФрд░ рд╕реНрдерд╛рдирд┐рдХ рдзреНрдпрд╛рди рд▓рд╛рдЧреВ рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward(self, x):
    """Apply channel and spatial attention on input for feature recalibration."""
    return x * self.act(self.cv1(torch.cat([torch.mean(x, 1, keepdim=True), torch.max(x, 1, keepdim=True)[0]], 1)))



ultralytics.nn.modules.conv.CBAM

рдХрд╛ рд░реВрдк: Module

рджреГрдврд╝ рдмреНрд▓реЙрдХ рдзреНрдпрд╛рди рдореЙрдбреНрдпреВрд▓ред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class CBAM(nn.Module):
    """Convolutional Block Attention Module."""

    def __init__(self, c1, kernel_size=7):
        """Initialize CBAM with given input channel (c1) and kernel size."""
        super().__init__()
        self.channel_attention = ChannelAttention(c1)
        self.spatial_attention = SpatialAttention(kernel_size)

    def forward(self, x):
        """Applies the forward pass through C1 module."""
        return self.spatial_attention(self.channel_attention(x))

__init__(c1, kernel_size=7)

рджрд┐рдП рдЧрдП рдЗрдирдкреБрдЯ рдЪреИрдирд▓ (c1) рдФрд░ рдХрд░реНрдиреЗрд▓ рдЖрдХрд╛рд░ рдХреЗ рд╕рд╛рде CBAM рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, c1, kernel_size=7):
    """Initialize CBAM with given input channel (c1) and kernel size."""
    super().__init__()
    self.channel_attention = ChannelAttention(c1)
    self.spatial_attention = SpatialAttention(kernel_size)

forward(x)

C1 рдореЙрдбреНрдпреВрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрдЧреЗ рдХреЗ рдкрд╛рд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward(self, x):
    """Applies the forward pass through C1 module."""
    return self.spatial_attention(self.channel_attention(x))



ultralytics.nn.modules.conv.Concat

рдХрд╛ рд░реВрдк: Module

рдЖрдпрд╛рдо рдХреЗ рд╕рд╛рде рдЯреЗрдВрд╕рд░ рдХреА рдПрдХ рд╕реВрдЪреА рдХреЛ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
class Concat(nn.Module):
    """Concatenate a list of tensors along dimension."""

    def __init__(self, dimension=1):
        """Concatenates a list of tensors along a specified dimension."""
        super().__init__()
        self.d = dimension

    def forward(self, x):
        """Forward pass for the YOLOv8 mask Proto module."""
        return torch.cat(x, self.d)

__init__(dimension=1)

рдПрдХ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЖрдпрд╛рдо рдХреЗ рд╕рд╛рде рдЯреЗрдВрд╕рд░ рдХреА рдПрдХ рд╕реВрдЪреА рдХреЛ рдЬреЛрдбрд╝рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def __init__(self, dimension=1):
    """Concatenates a list of tensors along a specified dimension."""
    super().__init__()
    self.d = dimension

forward(x)

рдХреЗ рд▓рд┐рдП рдлреЙрд░рд╡рд░реНрдб рдкрд╛рд╕ YOLOv8 рдорд╛рд╕реНрдХ рдкреНрд░реЛрдЯреЛ рдореЙрдбреНрдпреВрд▓ред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def forward(self, x):
    """Forward pass for the YOLOv8 mask Proto module."""
    return torch.cat(x, self.d)



ultralytics.nn.modules.conv.autopad(k, p=None, d=1)

рдкреИрдб рд╕реЗ 'рд╕рдорд╛рди' рдЖрдХрд╛рд░ рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ рджреЗрддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/nn/modules/conv.py
def autopad(k, p=None, d=1):  # kernel, padding, dilation
    """Pad to 'same' shape outputs."""
    if d > 1:
        k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k]  # actual kernel-size
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    return p





2023-11-12 рдмрдирд╛рдпрд╛ рдЧрдпрд╛, рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ 2023-11-25
рд▓реЗрдЦрдХ: рдЧреНрд▓реЗрди-рдЬреЛрдЪрд░ (3)