graft-pytorch 0.1.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- graft/__init__.py +20 -0
- graft/cli.py +62 -0
- graft/config.py +36 -0
- graft/decompositions.py +54 -0
- graft/genindices.py +122 -0
- graft/grad_dist.py +20 -0
- graft/models/BERT_model.py +40 -0
- graft/models/MobilenetV2.py +111 -0
- graft/models/ResNeXt.py +154 -0
- graft/models/__init__.py +22 -0
- graft/models/efficientnet.py +197 -0
- graft/models/efficientnetb7.py +268 -0
- graft/models/fashioncnn.py +69 -0
- graft/models/mobilenet.py +83 -0
- graft/models/resnet.py +564 -0
- graft/models/resnet9.py +72 -0
- graft/scheduler.py +63 -0
- graft/trainer.py +467 -0
- graft/utils/__init__.py +5 -0
- graft/utils/extras.py +37 -0
- graft/utils/generate.py +33 -0
- graft/utils/imagenetselloader.py +54 -0
- graft/utils/loader.py +293 -0
- graft/utils/model_mapper.py +45 -0
- graft/utils/pickler.py +27 -0
- graft_pytorch-0.1.7.dist-info/METADATA +302 -0
- graft_pytorch-0.1.7.dist-info/RECORD +31 -0
- graft_pytorch-0.1.7.dist-info/WHEEL +5 -0
- graft_pytorch-0.1.7.dist-info/entry_points.txt +2 -0
- graft_pytorch-0.1.7.dist-info/licenses/LICENSE +21 -0
- graft_pytorch-0.1.7.dist-info/top_level.txt +1 -0
@@ -0,0 +1,197 @@
|
|
1
|
+
'''EfficientNet in PyTorch.
|
2
|
+
|
3
|
+
Reference
|
4
|
+
EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks
|
5
|
+
https://github.com/keras-team/keras-applications/blob/master/keras_applications/efficientnet.py
|
6
|
+
'''
|
7
|
+
import torch
|
8
|
+
import torch.nn as nn
|
9
|
+
import torch.nn.functional as F
|
10
|
+
|
11
|
+
|
12
|
+
def swish(x):
|
13
|
+
return x * x.sigmoid()
|
14
|
+
|
15
|
+
|
16
|
+
def drop_connect(x, drop_ratio):
|
17
|
+
keep_ratio = 1.0 - drop_ratio
|
18
|
+
mask = torch.empty([x.shape[0], 1, 1, 1], dtype=x.dtype, device=x.device)
|
19
|
+
mask.bernoulli_(keep_ratio)
|
20
|
+
x.div_(keep_ratio)
|
21
|
+
x.mul_(mask)
|
22
|
+
return x
|
23
|
+
|
24
|
+
|
25
|
+
class SE(nn.Module):
|
26
|
+
'''Squeeze-and-Excitation block with Swish.'''
|
27
|
+
|
28
|
+
def __init__(self, in_channels, se_channels):
|
29
|
+
super(SE, self).__init__()
|
30
|
+
self.se1 = nn.Conv2d(in_channels, se_channels,
|
31
|
+
kernel_size=1, bias=True)
|
32
|
+
self.se2 = nn.Conv2d(se_channels, in_channels,
|
33
|
+
kernel_size=1, bias=True)
|
34
|
+
|
35
|
+
|
36
|
+
def forward(self, x):
|
37
|
+
out = F.adaptive_avg_pool2d(x, (1, 1))
|
38
|
+
out = swish(self.se1(out))
|
39
|
+
out = self.se2(out).sigmoid()
|
40
|
+
out = x * out
|
41
|
+
return out
|
42
|
+
|
43
|
+
|
44
|
+
class Block(nn.Module):
|
45
|
+
'''expansion + depthwise + pointwise + squeeze-excitation'''
|
46
|
+
|
47
|
+
def __init__(self,
|
48
|
+
in_channels,
|
49
|
+
out_channels,
|
50
|
+
kernel_size,
|
51
|
+
stride,
|
52
|
+
expand_ratio=1,
|
53
|
+
se_ratio=0.,
|
54
|
+
drop_rate=0.):
|
55
|
+
super(Block, self).__init__()
|
56
|
+
self.stride = stride
|
57
|
+
self.drop_rate = drop_rate
|
58
|
+
self.expand_ratio = expand_ratio
|
59
|
+
|
60
|
+
# Expansion
|
61
|
+
channels = expand_ratio * in_channels
|
62
|
+
self.conv1 = nn.Conv2d(in_channels,
|
63
|
+
channels,
|
64
|
+
kernel_size=1,
|
65
|
+
stride=1,
|
66
|
+
padding=0,
|
67
|
+
bias=False)
|
68
|
+
self.bn1 = nn.BatchNorm2d(channels)
|
69
|
+
|
70
|
+
# Depthwise conv
|
71
|
+
self.conv2 = nn.Conv2d(channels,
|
72
|
+
channels,
|
73
|
+
kernel_size=kernel_size,
|
74
|
+
stride=stride,
|
75
|
+
padding=(1 if kernel_size == 3 else 2),
|
76
|
+
groups=channels,
|
77
|
+
bias=False)
|
78
|
+
self.bn2 = nn.BatchNorm2d(channels)
|
79
|
+
|
80
|
+
# SE layers
|
81
|
+
se_channels = int(in_channels * se_ratio)
|
82
|
+
self.se = SE(channels, se_channels)
|
83
|
+
|
84
|
+
# Output
|
85
|
+
self.conv3 = nn.Conv2d(channels,
|
86
|
+
out_channels,
|
87
|
+
kernel_size=1,
|
88
|
+
stride=1,
|
89
|
+
padding=0,
|
90
|
+
bias=False)
|
91
|
+
self.bn3 = nn.BatchNorm2d(out_channels)
|
92
|
+
|
93
|
+
# Skip connection if in and out shapes are the same (MV-V2 style)
|
94
|
+
self.has_skip = (stride == 1) and (in_channels == out_channels)
|
95
|
+
|
96
|
+
|
97
|
+
def forward(self, x):
|
98
|
+
out = x if self.expand_ratio == 1 else swish(self.bn1(self.conv1(x)))
|
99
|
+
out = swish(self.bn2(self.conv2(out)))
|
100
|
+
out = self.se(out)
|
101
|
+
out = self.bn3(self.conv3(out))
|
102
|
+
if self.has_skip:
|
103
|
+
if self.training and self.drop_rate > 0:
|
104
|
+
out = drop_connect(out, self.drop_rate)
|
105
|
+
out = out + x
|
106
|
+
return out
|
107
|
+
|
108
|
+
|
109
|
+
class EfficientNet(nn.Module):
|
110
|
+
def __init__(self, cfg, num_classes=10):
|
111
|
+
super(EfficientNet, self).__init__()
|
112
|
+
self.cfg = cfg
|
113
|
+
self.conv1 = nn.Conv2d(3,
|
114
|
+
32,
|
115
|
+
kernel_size=3,
|
116
|
+
stride=1,
|
117
|
+
padding=1,
|
118
|
+
bias=False)
|
119
|
+
self.embDim = cfg['out_channels'][-1]
|
120
|
+
self.bn1 = nn.BatchNorm2d(32)
|
121
|
+
self.layers = self._make_layers(in_channels=32)
|
122
|
+
self.linear = nn.Linear(cfg['out_channels'][-1], num_classes)
|
123
|
+
|
124
|
+
|
125
|
+
def _make_layers(self, in_channels):
|
126
|
+
layers = []
|
127
|
+
cfg = [self.cfg[k] for k in ['expansion', 'out_channels', 'num_blocks', 'kernel_size',
|
128
|
+
'stride']]
|
129
|
+
b = 0
|
130
|
+
blocks = sum(self.cfg['num_blocks'])
|
131
|
+
for expansion, out_channels, num_blocks, kernel_size, stride in zip(*cfg):
|
132
|
+
strides = [stride] + [1] * (num_blocks - 1)
|
133
|
+
for stride in strides:
|
134
|
+
drop_rate = self.cfg['drop_connect_rate'] * b / blocks
|
135
|
+
layers.append(
|
136
|
+
Block(in_channels,
|
137
|
+
out_channels,
|
138
|
+
kernel_size,
|
139
|
+
stride,
|
140
|
+
expansion,
|
141
|
+
se_ratio=0.25,
|
142
|
+
drop_rate=drop_rate))
|
143
|
+
in_channels = out_channels
|
144
|
+
return nn.Sequential(*layers)
|
145
|
+
|
146
|
+
|
147
|
+
def forward(self, x, last=False, freeze=False):
|
148
|
+
if freeze:
|
149
|
+
with torch.no_grad():
|
150
|
+
out = swish(self.bn1(self.conv1(x)))
|
151
|
+
out = self.layers(out)
|
152
|
+
out = F.adaptive_avg_pool2d(out, 1)
|
153
|
+
e = out.view(out.size(0), -1)
|
154
|
+
dropout_rate = self.cfg['dropout_rate']
|
155
|
+
if self.training and dropout_rate > 0:
|
156
|
+
e = F.dropout(e, p=dropout_rate)
|
157
|
+
else:
|
158
|
+
out = swish(self.bn1(self.conv1(x)))
|
159
|
+
out = self.layers(out)
|
160
|
+
out = F.adaptive_avg_pool2d(out, 1)
|
161
|
+
e = out.view(out.size(0), -1)
|
162
|
+
dropout_rate = self.cfg['dropout_rate']
|
163
|
+
if self.training and dropout_rate > 0:
|
164
|
+
e = F.dropout(e, p=dropout_rate)
|
165
|
+
out = self.linear(e)
|
166
|
+
if last:
|
167
|
+
return out, e
|
168
|
+
else:
|
169
|
+
return out
|
170
|
+
|
171
|
+
|
172
|
+
def get_embedding_dim(self):
|
173
|
+
return self.embDim
|
174
|
+
|
175
|
+
|
176
|
+
def EfficientNetB0(num_classes=10):
|
177
|
+
cfg = {
|
178
|
+
'num_blocks': [1, 2, 2, 3, 3, 4, 1],
|
179
|
+
'expansion': [1, 6, 6, 6, 6, 6, 6],
|
180
|
+
'out_channels': [16, 24, 40, 80, 112, 192, 320],
|
181
|
+
'kernel_size': [3, 3, 5, 3, 5, 5, 3],
|
182
|
+
'stride': [1, 2, 2, 2, 1, 2, 1],
|
183
|
+
'dropout_rate': 0.2,
|
184
|
+
'drop_connect_rate': 0.2,
|
185
|
+
}
|
186
|
+
return EfficientNet(cfg, num_classes)
|
187
|
+
|
188
|
+
|
189
|
+
def test():
|
190
|
+
net = EfficientNetB0()
|
191
|
+
x = torch.randn(2, 3, 32, 32)
|
192
|
+
y = net(x)
|
193
|
+
print(y.shape)
|
194
|
+
|
195
|
+
|
196
|
+
if __name__ == '__main__':
|
197
|
+
test()
|
@@ -0,0 +1,268 @@
|
|
1
|
+
import torch
|
2
|
+
import torch.nn as nn
|
3
|
+
import torch.nn.functional as F
|
4
|
+
from torch.autograd import Variable
|
5
|
+
|
6
|
+
import math
|
7
|
+
|
8
|
+
class Swish(nn.Module):
|
9
|
+
def __init__(self):
|
10
|
+
super(Swish, self).__init__()
|
11
|
+
|
12
|
+
self.sigmoid = nn.Sigmoid()
|
13
|
+
|
14
|
+
def forward(self, x):
|
15
|
+
return x * self.sigmoid(x)
|
16
|
+
|
17
|
+
def _RoundChannels(c, divisor=8, min_value=None):
|
18
|
+
if min_value is None:
|
19
|
+
min_value = divisor
|
20
|
+
new_c = max(min_value, int(c + divisor / 2) // divisor * divisor)
|
21
|
+
if new_c < 0.9 * c:
|
22
|
+
new_c += divisor
|
23
|
+
return new_c
|
24
|
+
|
25
|
+
def _RoundRepeats(r):
|
26
|
+
return int(math.ceil(r))
|
27
|
+
|
28
|
+
def _DropPath(x, drop_prob, training):
|
29
|
+
if drop_prob > 0 and training:
|
30
|
+
keep_prob = 1 - drop_prob
|
31
|
+
if x.is_cuda:
|
32
|
+
mask = Variable(torch.cuda.FloatTensor(x.size(0), 1, 1, 1).bernoulli_(keep_prob))
|
33
|
+
else:
|
34
|
+
mask = Variable(torch.FloatTensor(x.size(0), 1, 1, 1).bernoulli_(keep_prob))
|
35
|
+
x.div_(keep_prob)
|
36
|
+
x.mul_(mask)
|
37
|
+
|
38
|
+
return x
|
39
|
+
|
40
|
+
def _BatchNorm(channels, eps=1e-3, momentum=0.01):
|
41
|
+
return nn.BatchNorm2d(channels, eps=eps, momentum=momentum)
|
42
|
+
|
43
|
+
def _Conv3x3Bn(in_channels, out_channels, stride):
|
44
|
+
return nn.Sequential(
|
45
|
+
nn.Conv2d(in_channels, out_channels, 3, stride, 1, bias=False),
|
46
|
+
_BatchNorm(out_channels),
|
47
|
+
Swish()
|
48
|
+
)
|
49
|
+
|
50
|
+
def _Conv1x1Bn(in_channels, out_channels):
|
51
|
+
return nn.Sequential(
|
52
|
+
nn.Conv2d(in_channels, out_channels, 1, 1, 0, bias=False),
|
53
|
+
_BatchNorm(out_channels),
|
54
|
+
Swish()
|
55
|
+
)
|
56
|
+
|
57
|
+
class SqueezeAndExcite(nn.Module):
|
58
|
+
def __init__(self, channels, squeeze_channels, se_ratio):
|
59
|
+
super(SqueezeAndExcite, self).__init__()
|
60
|
+
|
61
|
+
squeeze_channels = squeeze_channels * se_ratio
|
62
|
+
if not squeeze_channels.is_integer():
|
63
|
+
raise ValueError('channels must be divisible by 1/ratio')
|
64
|
+
|
65
|
+
squeeze_channels = int(squeeze_channels)
|
66
|
+
self.se_reduce = nn.Conv2d(channels, squeeze_channels, 1, 1, 0, bias=True)
|
67
|
+
self.non_linear1 = Swish()
|
68
|
+
self.se_expand = nn.Conv2d(squeeze_channels, channels, 1, 1, 0, bias=True)
|
69
|
+
self.non_linear2 = nn.Sigmoid()
|
70
|
+
|
71
|
+
def forward(self, x):
|
72
|
+
y = torch.mean(x, (2, 3), keepdim=True)
|
73
|
+
y = self.non_linear1(self.se_reduce(y))
|
74
|
+
y = self.non_linear2(self.se_expand(y))
|
75
|
+
y = x * y
|
76
|
+
|
77
|
+
return y
|
78
|
+
|
79
|
+
class MBConvBlock(nn.Module):
|
80
|
+
def __init__(self, in_channels, out_channels, kernel_size, stride, expand_ratio, se_ratio, drop_path_rate):
|
81
|
+
super(MBConvBlock, self).__init__()
|
82
|
+
|
83
|
+
expand = (expand_ratio != 1)
|
84
|
+
expand_channels = in_channels * expand_ratio
|
85
|
+
se = (se_ratio != 0.0)
|
86
|
+
self.residual_connection = (stride == 1 and in_channels == out_channels)
|
87
|
+
self.drop_path_rate = drop_path_rate
|
88
|
+
|
89
|
+
conv = []
|
90
|
+
|
91
|
+
if expand:
|
92
|
+
# expansion phase
|
93
|
+
pw_expansion = nn.Sequential(
|
94
|
+
nn.Conv2d(in_channels, expand_channels, 1, 1, 0, bias=False),
|
95
|
+
_BatchNorm(expand_channels),
|
96
|
+
Swish()
|
97
|
+
)
|
98
|
+
conv.append(pw_expansion)
|
99
|
+
|
100
|
+
# depthwise convolution phase
|
101
|
+
dw = nn.Sequential(
|
102
|
+
nn.Conv2d(
|
103
|
+
expand_channels,
|
104
|
+
expand_channels,
|
105
|
+
kernel_size,
|
106
|
+
stride,
|
107
|
+
kernel_size//2,
|
108
|
+
groups=expand_channels,
|
109
|
+
bias=False
|
110
|
+
),
|
111
|
+
_BatchNorm(expand_channels),
|
112
|
+
Swish()
|
113
|
+
)
|
114
|
+
conv.append(dw)
|
115
|
+
|
116
|
+
if se:
|
117
|
+
# squeeze and excite
|
118
|
+
squeeze_excite = SqueezeAndExcite(expand_channels, in_channels, se_ratio)
|
119
|
+
conv.append(squeeze_excite)
|
120
|
+
|
121
|
+
# projection phase
|
122
|
+
pw_projection = nn.Sequential(
|
123
|
+
nn.Conv2d(expand_channels, out_channels, 1, 1, 0, bias=False),
|
124
|
+
_BatchNorm(out_channels)
|
125
|
+
)
|
126
|
+
conv.append(pw_projection)
|
127
|
+
|
128
|
+
self.conv = nn.Sequential(*conv)
|
129
|
+
|
130
|
+
def forward(self, x):
|
131
|
+
if self.residual_connection:
|
132
|
+
return x + _DropPath(self.conv(x), self.drop_path_rate, self.training)
|
133
|
+
else:
|
134
|
+
return self.conv(x)
|
135
|
+
|
136
|
+
class EfficientNet(nn.Module):
|
137
|
+
config = [
|
138
|
+
#(in_channels, out_channels, kernel_size, stride, expand_ratio, se_ratio, repeats)
|
139
|
+
[32, 16, 3, 1, 1, 0.25, 1],
|
140
|
+
[16, 24, 3, 2, 6, 0.25, 2],
|
141
|
+
[24, 40, 5, 2, 6, 0.25, 2],
|
142
|
+
[40, 80, 3, 2, 6, 0.25, 3],
|
143
|
+
[80, 112, 5, 1, 6, 0.25, 3],
|
144
|
+
[112, 192, 5, 2, 6, 0.25, 4],
|
145
|
+
[192, 320, 3, 1, 6, 0.25, 1]
|
146
|
+
]
|
147
|
+
|
148
|
+
def __init__(self, param, num_classes=100, stem_channels=32, feature_size=1280, drop_connect_rate=0.2):
|
149
|
+
super(EfficientNet, self).__init__()
|
150
|
+
|
151
|
+
# scaling width
|
152
|
+
width_coefficient = param[0]
|
153
|
+
if width_coefficient != 1.0:
|
154
|
+
stem_channels = _RoundChannels(stem_channels*width_coefficient)
|
155
|
+
for conf in self.config:
|
156
|
+
conf[0] = _RoundChannels(conf[0]*width_coefficient)
|
157
|
+
conf[1] = _RoundChannels(conf[1]*width_coefficient)
|
158
|
+
|
159
|
+
# scaling depth
|
160
|
+
depth_coefficient = param[1]
|
161
|
+
if depth_coefficient != 1.0:
|
162
|
+
for conf in self.config:
|
163
|
+
conf[6] = _RoundRepeats(conf[6]*depth_coefficient)
|
164
|
+
|
165
|
+
# scaling resolution
|
166
|
+
input_size = param[2]
|
167
|
+
|
168
|
+
# stem convolution
|
169
|
+
self.stem_conv = _Conv3x3Bn(3, stem_channels, 2)
|
170
|
+
|
171
|
+
# total #blocks
|
172
|
+
total_blocks = 0
|
173
|
+
for conf in self.config:
|
174
|
+
total_blocks += conf[6]
|
175
|
+
|
176
|
+
# mobile inverted bottleneck
|
177
|
+
blocks = []
|
178
|
+
for in_channels, out_channels, kernel_size, stride, expand_ratio, se_ratio, repeats in self.config:
|
179
|
+
# drop connect rate based on block index
|
180
|
+
drop_rate = drop_connect_rate * (len(blocks) / total_blocks)
|
181
|
+
blocks.append(MBConvBlock(in_channels, out_channels, kernel_size, stride, expand_ratio, se_ratio, drop_rate))
|
182
|
+
for _ in range(repeats-1):
|
183
|
+
drop_rate = drop_connect_rate * (len(blocks) / total_blocks)
|
184
|
+
blocks.append(MBConvBlock(out_channels, out_channels, kernel_size, 1, expand_ratio, se_ratio, drop_rate))
|
185
|
+
self.blocks = nn.Sequential(*blocks)
|
186
|
+
|
187
|
+
# last several layers
|
188
|
+
self.head_conv = _Conv1x1Bn(self.config[-1][1], feature_size)
|
189
|
+
#self.avgpool = nn.AvgPool2d(input_size//32, stride=1)
|
190
|
+
self.dropout = nn.Dropout(param[3])
|
191
|
+
self.classifier = nn.Linear(feature_size, num_classes)
|
192
|
+
|
193
|
+
self._initialize_weights()
|
194
|
+
|
195
|
+
def forward(self, x, last=False, freeze=False):
|
196
|
+
if freeze:
|
197
|
+
with torch.no_grad():
|
198
|
+
x = self.stem_conv(x)
|
199
|
+
x = self.blocks(x)
|
200
|
+
x = self.head_conv(x)
|
201
|
+
#x = self.avgpool(x)
|
202
|
+
#x = x.view(x.size(0), -1)
|
203
|
+
x = torch.mean(x, (2, 3))
|
204
|
+
e = self.dropout(x)
|
205
|
+
# x = self.classifier(x)
|
206
|
+
else:
|
207
|
+
x = self.stem_conv(x)
|
208
|
+
x = self.blocks(x)
|
209
|
+
x = self.head_conv(x)
|
210
|
+
#x = self.avgpool(x)
|
211
|
+
#x = x.view(x.size(0), -1)
|
212
|
+
x = torch.mean(x, (2, 3))
|
213
|
+
e = self.dropout(x)
|
214
|
+
out = self.classifier(x)
|
215
|
+
if last:
|
216
|
+
return out, e
|
217
|
+
else:
|
218
|
+
return out
|
219
|
+
|
220
|
+
def _initialize_weights(self):
|
221
|
+
for m in self.modules():
|
222
|
+
if isinstance(m, nn.Conv2d):
|
223
|
+
n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
|
224
|
+
m.weight.data.normal_(0, math.sqrt(2.0 / n))
|
225
|
+
if m.bias is not None:
|
226
|
+
m.bias.data.zero_()
|
227
|
+
elif isinstance(m, nn.BatchNorm2d):
|
228
|
+
m.weight.data.fill_(1)
|
229
|
+
m.bias.data.zero_()
|
230
|
+
elif isinstance(m, nn.Linear):
|
231
|
+
n = m.weight.size(1)
|
232
|
+
m.weight.data.normal_(0, 0.01)
|
233
|
+
m.bias.data.zero_()
|
234
|
+
|
235
|
+
def EfficientNetB7(num_classes=100):
|
236
|
+
net_param = {
|
237
|
+
# 'efficientnet type': (width_coef, depth_coef, resolution, dropout_rate)
|
238
|
+
'efficientnet-b0': (1.0, 1.0, 224, 0.2),
|
239
|
+
'efficientnet-b1': (1.0, 1.1, 240, 0.2),
|
240
|
+
'efficientnet-b2': (1.1, 1.2, 260, 0.3),
|
241
|
+
'efficientnet-b3': (1.2, 1.4, 300, 0.3),
|
242
|
+
'efficientnet-b4': (1.4, 1.8, 380, 0.4),
|
243
|
+
'efficientnet-b5': (1.6, 2.2, 456, 0.4),
|
244
|
+
'efficientnet-b6': (1.8, 2.6, 528, 0.5),
|
245
|
+
'efficientnet-b7': (2.0, 3.1, 600, 0.5)
|
246
|
+
}
|
247
|
+
|
248
|
+
param = net_param['efficientnet-b7']
|
249
|
+
#net = EfficientNet(param)
|
250
|
+
return EfficientNet(param, num_classes)
|
251
|
+
|
252
|
+
if __name__ == '__main__':
|
253
|
+
net_param = {
|
254
|
+
# 'efficientnet type': (width_coef, depth_coef, resolution, dropout_rate)
|
255
|
+
'efficientnet-b0': (1.0, 1.0, 224, 0.2),
|
256
|
+
'efficientnet-b1': (1.0, 1.1, 240, 0.2),
|
257
|
+
'efficientnet-b2': (1.1, 1.2, 260, 0.3),
|
258
|
+
'efficientnet-b3': (1.2, 1.4, 300, 0.3),
|
259
|
+
'efficientnet-b4': (1.4, 1.8, 380, 0.4),
|
260
|
+
'efficientnet-b5': (1.6, 2.2, 456, 0.4),
|
261
|
+
'efficientnet-b6': (1.8, 2.6, 528, 0.5),
|
262
|
+
'efficientnet-b7': (2.0, 3.1, 600, 0.5)
|
263
|
+
}
|
264
|
+
|
265
|
+
param = net_param['efficientnet-b0']
|
266
|
+
net = EfficientNet(param)
|
267
|
+
x_image = Variable(torch.randn(1, 3, param[2], param[2]))
|
268
|
+
y = net(x_image)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import torch.nn as nn
|
2
|
+
import torch
|
3
|
+
from torch import Tensor
|
4
|
+
|
5
|
+
|
6
|
+
class FashionCNN(nn.Module):
|
7
|
+
|
8
|
+
def __init__(self,in_channels, num_classes):
|
9
|
+
super(FashionCNN, self).__init__()
|
10
|
+
|
11
|
+
self.layer1 = nn.Sequential(
|
12
|
+
nn.Conv2d(in_channels=in_channels, out_channels=32, kernel_size=3, padding=1),
|
13
|
+
nn.BatchNorm2d(32),
|
14
|
+
nn.ReLU(),
|
15
|
+
nn.MaxPool2d(kernel_size=2, stride=2)
|
16
|
+
)
|
17
|
+
|
18
|
+
self.layer2 = nn.Sequential(
|
19
|
+
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3),
|
20
|
+
nn.BatchNorm2d(64),
|
21
|
+
nn.ReLU(),
|
22
|
+
nn.MaxPool2d(2)
|
23
|
+
)
|
24
|
+
|
25
|
+
self.fc1 = nn.Linear(in_features=64*6*6, out_features=600)
|
26
|
+
self.drop = nn.Dropout2d(0.25)
|
27
|
+
self.fc2 = nn.Linear(in_features=600, out_features=120)
|
28
|
+
self.fc3 = nn.Linear(in_features=120, out_features=num_classes)
|
29
|
+
|
30
|
+
# def forward(self, x):
|
31
|
+
# out = self.layer1(x)
|
32
|
+
# out = self.layer2(out)
|
33
|
+
# out = out.view(out.size(0), -1)
|
34
|
+
# out = self.fc1(out)
|
35
|
+
# out = self.drop(out)
|
36
|
+
# out = self.fc2(out)
|
37
|
+
# out = self.fc3(out)
|
38
|
+
|
39
|
+
# return out
|
40
|
+
|
41
|
+
def forward(self, x: Tensor, last=False, freeze=False) -> Tensor:
|
42
|
+
# See note [TorchScript super()]
|
43
|
+
if freeze:
|
44
|
+
with torch.no_grad():
|
45
|
+
self.eval()
|
46
|
+
x = self.layer1(x)
|
47
|
+
x = self.layer2(x)
|
48
|
+
x = x.view(x.size(0), -1)
|
49
|
+
x = self.fc1(x)
|
50
|
+
x = self.drop(x)
|
51
|
+
x = self.fc2(x)
|
52
|
+
# x = self.fc3(x)
|
53
|
+
features = torch.flatten(x, 1)
|
54
|
+
self.train()
|
55
|
+
else:
|
56
|
+
x = self.layer1(x)
|
57
|
+
x = self.layer2(x)
|
58
|
+
x = x.view(x.size(0), -1)
|
59
|
+
x = self.fc1(x)
|
60
|
+
x = self.drop(x)
|
61
|
+
x = self.fc2(x)
|
62
|
+
# x = self.fc3(x)
|
63
|
+
features = torch.flatten(x, 1)
|
64
|
+
|
65
|
+
out = self.fc3(features)
|
66
|
+
if last:
|
67
|
+
return out, features
|
68
|
+
else:
|
69
|
+
return out
|
@@ -0,0 +1,83 @@
|
|
1
|
+
'''MobileNet in PyTorch.
|
2
|
+
|
3
|
+
Reference
|
4
|
+
MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications
|
5
|
+
https://arxiv.org/abs/1704.04861
|
6
|
+
'''
|
7
|
+
|
8
|
+
|
9
|
+
import torch
|
10
|
+
import torch.nn as nn
|
11
|
+
import torch.nn.functional as F
|
12
|
+
|
13
|
+
|
14
|
+
class Block(nn.Module):
|
15
|
+
'''Depthwise conv + Pointwise conv'''
|
16
|
+
|
17
|
+
def __init__(self, in_planes, out_planes, stride=1):
|
18
|
+
super(Block, self).__init__()
|
19
|
+
self.conv1 = nn.Conv2d(in_planes, in_planes, kernel_size=3, stride=stride, padding=1, groups=in_planes, bias=False)
|
20
|
+
self.bn1 = nn.BatchNorm2d(in_planes)
|
21
|
+
self.conv2 = nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=1, padding=0, bias=False)
|
22
|
+
self.bn2 = nn.BatchNorm2d(out_planes)
|
23
|
+
|
24
|
+
|
25
|
+
def forward(self, x):
|
26
|
+
out = F.relu(self.bn1(self.conv1(x)))
|
27
|
+
out = F.relu(self.bn2(self.conv2(out)))
|
28
|
+
return out
|
29
|
+
|
30
|
+
|
31
|
+
class MobileNet(nn.Module):
|
32
|
+
# (128,2) means conv planes=128, conv stride=2, by default conv stride=1
|
33
|
+
cfg = [64, (128,2), 128, (256,2), 256, (512,2), 512, 512, 512, 512, 512, (1024,2), 1024]
|
34
|
+
|
35
|
+
def __init__(self, num_classes=10):
|
36
|
+
super(MobileNet, self).__init__()
|
37
|
+
self.embDim = 1024
|
38
|
+
|
39
|
+
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1, bias=False)
|
40
|
+
self.bn1 = nn.BatchNorm2d(32)
|
41
|
+
self.layers = self._make_layers(in_planes=32)
|
42
|
+
self.linear = nn.Linear(1024, num_classes)
|
43
|
+
|
44
|
+
|
45
|
+
def _make_layers(self, in_planes):
|
46
|
+
layers = []
|
47
|
+
for x in self.cfg:
|
48
|
+
out_planes = x if isinstance(x, int) else x[0]
|
49
|
+
stride = 1 if isinstance(x, int) else x[1]
|
50
|
+
layers.append(Block(in_planes, out_planes, stride))
|
51
|
+
in_planes = out_planes
|
52
|
+
return nn.Sequential(*layers)
|
53
|
+
|
54
|
+
|
55
|
+
def forward(self, x, last=False, freeze=False):
|
56
|
+
if freeze:
|
57
|
+
with torch.no_grad():
|
58
|
+
out = F.relu(self.bn1(self.conv1(x)))
|
59
|
+
out = self.layers(out)
|
60
|
+
out = F.avg_pool2d(out, 2)
|
61
|
+
e = out.view(out.size(0), -1)
|
62
|
+
else:
|
63
|
+
out = F.relu(self.bn1(self.conv1(x)))
|
64
|
+
out = self.layers(out)
|
65
|
+
out = F.avg_pool2d(out, 2)
|
66
|
+
e = out.view(out.size(0), -1)
|
67
|
+
out = self.linear(e)
|
68
|
+
if last:
|
69
|
+
return out, e
|
70
|
+
else:
|
71
|
+
return out
|
72
|
+
|
73
|
+
def get_embedding_dim(self):
|
74
|
+
return self.embDim
|
75
|
+
|
76
|
+
|
77
|
+
def test():
|
78
|
+
net = MobileNet()
|
79
|
+
x = torch.randn(1, 3, 32, 32)
|
80
|
+
y = net(x)
|
81
|
+
print(y.size())
|
82
|
+
|
83
|
+
# test()
|