MCPcopy Create free account
hub / github.com/QWTforGithub/T2LDM / SelectiveKernel

Class SelectiveKernel

timm/models/layers/selective_kernel.py:49–119  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

47
48
49class SelectiveKernel(nn.Module):
50
51 def __init__(self, in_channels, out_channels=None, kernel_size=None, stride=1, dilation=1, groups=1,
52 rd_ratio=1./16, rd_channels=None, rd_divisor=8, keep_3x3=True, split_input=True,
53 drop_block=None, act_layer=nn.ReLU, norm_layer=nn.BatchNorm2d, aa_layer=None):
54 """ Selective Kernel Convolution Module
55
56 As described in Selective Kernel Networks (https://arxiv.org/abs/1903.06586) with some modifications.
57
58 Largest change is the input split, which divides the input channels across each convolution path, this can
59 be viewed as a grouping of sorts, but the output channel counts expand to the module level value. This keeps
60 the parameter count from ballooning when the convolutions themselves don't have groups, but still provides
61 a noteworthy increase in performance over similar param count models without this attention layer. -Ross W
62
63 Args:
64 in_channels (int): module input (feature) channel count
65 out_channels (int): module output (feature) channel count
66 kernel_size (int, list): kernel size for each convolution branch
67 stride (int): stride for convolutions
68 dilation (int): dilation for module as a whole, impacts dilation of each branch
69 groups (int): number of groups for each branch
70 rd_ratio (int, float): reduction factor for attention features
71 keep_3x3 (bool): keep all branch convolution kernels as 3x3, changing larger kernels for dilations
72 split_input (bool): split input channels evenly across each convolution branch, keeps param count lower,
73 can be viewed as grouping by path, output expands to module out_channels count
74 drop_block (nn.Module): drop block module
75 act_layer (nn.Module): activation layer to use
76 norm_layer (nn.Module): batchnorm/norm layer to use
77 """
78 super(SelectiveKernel, self).__init__()
79 out_channels = out_channels or in_channels
80 kernel_size = kernel_size or [3, 5] # default to one 3x3 and one 5x5 branch. 5x5 -> 3x3 + dilation
81 _kernel_valid(kernel_size)
82 if not isinstance(kernel_size, list):
83 kernel_size = [kernel_size] * 2
84 if keep_3x3:
85 dilation = [dilation * (k - 1) // 2 for k in kernel_size]
86 kernel_size = [3] * len(kernel_size)
87 else:
88 dilation = [dilation] * len(kernel_size)
89 self.num_paths = len(kernel_size)
90 self.in_channels = in_channels
91 self.out_channels = out_channels
92 self.split_input = split_input
93 if self.split_input:
94 assert in_channels % self.num_paths == 0
95 in_channels = in_channels // self.num_paths
96 groups = min(out_channels, groups)
97
98 conv_kwargs = dict(
99 stride=stride, groups=groups, drop_block=drop_block, act_layer=act_layer, norm_layer=norm_layer,
100 aa_layer=aa_layer)
101 self.paths = nn.ModuleList([
102 ConvBnAct(in_channels, out_channels, kernel_size=k, dilation=d, **conv_kwargs)
103 for k, d in zip(kernel_size, dilation)])
104
105 attn_channels = rd_channels or make_divisible(out_channels * rd_ratio, divisor=rd_divisor)
106 self.attn = SelectiveKernelAttn(out_channels, self.num_paths, attn_channels)

Callers 2

__init__Method · 0.85
__init__Method · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected