Skip to content

Commit 75ca1bf

Browse files
authored
Merge branch 'master' into patch-1
2 parents b294ed9 + 45834ee commit 75ca1bf

File tree

7 files changed

+70
-31
lines changed

7 files changed

+70
-31
lines changed

.github/workflows/main.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Workflow
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
8+
jobs:
9+
pypi-job:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v2
13+
- name: Install twine
14+
run: pip install twine
15+
- name: Build package
16+
run: python setup.py sdist
17+
- name: Publish a Python distribution to PyPI
18+
uses: pypa/gh-action-pypi-publish@release/v1
19+
with:
20+
user: __token__
21+
password: ${{ secrets.PYPI_API_TOKEN }}

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@ model = EfficientNet.from_pretrained('efficientnet-b0')
1010

1111
### Updates
1212

13+
#### Update (April 2, 2021)
14+
15+
The [EfficientNetV2 paper](https://arxiv.org/abs/2104.00298) has been released! I am working on implementing it as you read this :)
16+
17+
About EfficientNetV2:
18+
> EfficientNetV2 is a new family of convolutional networks that have faster training speed and better parameter efficiency than previous models. To develop this family of models, we use a combination of training-aware neural architecture search and scaling, to jointly optimize training speed and parameter efficiency. The models were searched from the search space enriched with new ops such as Fused-MBConv.
19+
20+
Here is a comparison:
21+
> <img src="https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/efficientnetv2-image.png" width="100%" />
22+
23+
1324
#### Update (Aug 25, 2020)
1425

1526
This update adds:

efficientnet_pytorch/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "0.7.0"
1+
__version__ = "0.7.1"
22
from .model import EfficientNet, VALID_MODELS
33
from .utils import (
44
GlobalParams,

efficientnet_pytorch/model.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class MBConvBlock(nn.Module):
5050
def __init__(self, block_args, global_params, image_size=None):
5151
super().__init__()
5252
self._block_args = block_args
53-
self._bn_mom = 1 - global_params.batch_norm_momentum # pytorch's difference from tensorflow
53+
self._bn_mom = 1 - global_params.batch_norm_momentum # pytorch's difference from tensorflow
5454
self._bn_eps = global_params.batch_norm_epsilon
5555
self.has_se = (self._block_args.se_ratio is not None) and (0 < self._block_args.se_ratio <= 1)
5656
self.id_skip = block_args.id_skip # whether to use skip connection and drop connect
@@ -152,9 +152,7 @@ class EfficientNet(nn.Module):
152152
[1] https://arxiv.org/abs/1905.11946 (EfficientNet)
153153
154154
Example:
155-
156-
157-
import torch
155+
>>> import torch
158156
>>> from efficientnet.model import EfficientNet
159157
>>> inputs = torch.rand(1, 3, 224, 224)
160158
>>> model = EfficientNet.from_pretrained('efficientnet-b0')
@@ -198,7 +196,7 @@ def __init__(self, blocks_args=None, global_params=None):
198196
# The first block needs to take care of stride and filter size increase.
199197
self._blocks.append(MBConvBlock(block_args, self._global_params, image_size=image_size))
200198
image_size = calculate_output_image_size(image_size, block_args.stride)
201-
if block_args.num_repeat > 1: # modify block_args to keep same output size
199+
if block_args.num_repeat > 1: # modify block_args to keep same output size
202200
block_args = block_args._replace(input_filters=block_args.output_filters, stride=1)
203201
for _ in range(block_args.num_repeat - 1):
204202
self._blocks.append(MBConvBlock(block_args, self._global_params, image_size=image_size))
@@ -213,16 +211,18 @@ def __init__(self, blocks_args=None, global_params=None):
213211

214212
# Final linear layer
215213
self._avg_pooling = nn.AdaptiveAvgPool2d(1)
216-
self._dropout = nn.Dropout(self._global_params.dropout_rate)
217-
self._fc = nn.Linear(out_channels, self._global_params.num_classes)
214+
if self._global_params.include_top:
215+
self._dropout = nn.Dropout(self._global_params.dropout_rate)
216+
self._fc = nn.Linear(out_channels, self._global_params.num_classes)
217+
218+
# set activation to memory efficient swish by default
218219
self._swish = MemoryEfficientSwish()
219220

220221
def set_swish(self, memory_efficient=True):
221222
"""Sets swish function as memory efficient (for training) or standard (for export).
222223
223224
Args:
224225
memory_efficient (bool): Whether to use memory-efficient version of swish.
225-
226226
"""
227227
self._swish = MemoryEfficientSwish() if memory_efficient else Swish()
228228
for block in self._blocks:
@@ -261,17 +261,17 @@ def extract_endpoints(self, inputs):
261261
for idx, block in enumerate(self._blocks):
262262
drop_connect_rate = self._global_params.drop_connect_rate
263263
if drop_connect_rate:
264-
drop_connect_rate *= float(idx) / len(self._blocks) # scale drop connect_rate
264+
drop_connect_rate *= float(idx) / len(self._blocks) # scale drop connect_rate
265265
x = block(x, drop_connect_rate=drop_connect_rate)
266266
if prev_x.size(2) > x.size(2):
267-
endpoints['reduction_{}'.format(len(endpoints)+1)] = prev_x
267+
endpoints['reduction_{}'.format(len(endpoints) + 1)] = prev_x
268268
elif idx == len(self._blocks) - 1:
269-
endpoints['reduction_{}'.format(len(endpoints)+1)] = x
269+
endpoints['reduction_{}'.format(len(endpoints) + 1)] = x
270270
prev_x = x
271271

272272
# Head
273273
x = self._swish(self._bn1(self._conv_head(x)))
274-
endpoints['reduction_{}'.format(len(endpoints)+1)] = x
274+
endpoints['reduction_{}'.format(len(endpoints) + 1)] = x
275275

276276
return endpoints
277277

@@ -292,7 +292,7 @@ def extract_features(self, inputs):
292292
for idx, block in enumerate(self._blocks):
293293
drop_connect_rate = self._global_params.drop_connect_rate
294294
if drop_connect_rate:
295-
drop_connect_rate *= float(idx) / len(self._blocks) # scale drop connect_rate
295+
drop_connect_rate *= float(idx) / len(self._blocks) # scale drop connect_rate
296296
x = block(x, drop_connect_rate=drop_connect_rate)
297297

298298
# Head
@@ -322,7 +322,7 @@ def forward(self, inputs):
322322

323323
@classmethod
324324
def from_name(cls, model_name, in_channels=3, **override_params):
325-
"""create an efficientnet model according to name.
325+
"""Create an efficientnet model according to name.
326326
327327
Args:
328328
model_name (str): Name for efficientnet.
@@ -348,7 +348,7 @@ def from_name(cls, model_name, in_channels=3, **override_params):
348348
@classmethod
349349
def from_pretrained(cls, model_name, weights_path=None, advprop=False,
350350
in_channels=3, num_classes=1000, **override_params):
351-
"""create an efficientnet model according to name.
351+
"""Create an efficientnet model according to name.
352352
353353
Args:
354354
model_name (str): Name for efficientnet.
@@ -375,7 +375,8 @@ def from_pretrained(cls, model_name, weights_path=None, advprop=False,
375375
A pretrained efficientnet model.
376376
"""
377377
model = cls.from_name(model_name, num_classes=num_classes, **override_params)
378-
load_pretrained_weights(model, model_name, weights_path=weights_path, load_fc=(num_classes == 1000), advprop=advprop)
378+
load_pretrained_weights(model, model_name, weights_path=weights_path,
379+
load_fc=(num_classes == 1000), advprop=advprop)
379380
model._change_in_channels(in_channels)
380381
return model
381382

efficientnet_pytorch/utils.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818

1919
################################################################################
20-
### Help functions for model architecture
20+
# Help functions for model architecture
2121
################################################################################
2222

2323
# GlobalParams and BlockArgs: Two namedtuples
@@ -50,11 +50,14 @@
5050
GlobalParams.__new__.__defaults__ = (None,) * len(GlobalParams._fields)
5151
BlockArgs.__new__.__defaults__ = (None,) * len(BlockArgs._fields)
5252

53-
54-
# An ordinary implementation of Swish function
55-
class Swish(nn.Module):
56-
def forward(self, x):
57-
return x * torch.sigmoid(x)
53+
# Swish activation function
54+
if hasattr(nn, 'SiLU'):
55+
Swish = nn.SiLU
56+
else:
57+
# For compatibility with old PyTorch versions
58+
class Swish(nn.Module):
59+
def forward(self, x):
60+
return x * torch.sigmoid(x)
5861

5962

6063
# A memory-efficient implementation of Swish function
@@ -71,6 +74,7 @@ def backward(ctx, grad_output):
7174
sigmoid_i = torch.sigmoid(i)
7275
return grad_output * (sigmoid_i * (1 + i * (1 - sigmoid_i)))
7376

77+
7478
class MemoryEfficientSwish(nn.Module):
7579
def forward(self, x):
7680
return SwishImplementation.apply(x)
@@ -96,10 +100,10 @@ def round_filters(filters, global_params):
96100
divisor = global_params.depth_divisor
97101
min_depth = global_params.min_depth
98102
filters *= multiplier
99-
min_depth = min_depth or divisor # pay attention to this line when using min_depth
103+
min_depth = min_depth or divisor # pay attention to this line when using min_depth
100104
# follow the formula transferred from official TensorFlow implementation
101105
new_filters = max(min_depth, int(filters + divisor / 2) // divisor * divisor)
102-
if new_filters < 0.9 * filters: # prevent rounding by more than 10%
106+
if new_filters < 0.9 * filters: # prevent rounding by more than 10%
103107
new_filters += divisor
104108
return int(new_filters)
105109

@@ -233,7 +237,7 @@ def forward(self, x):
233237
ih, iw = x.size()[-2:]
234238
kh, kw = self.weight.size()[-2:]
235239
sh, sw = self.stride
236-
oh, ow = math.ceil(ih / sh), math.ceil(iw / sw) # change the output size according to stride ! ! !
240+
oh, ow = math.ceil(ih / sh), math.ceil(iw / sw) # change the output size according to stride ! ! !
237241
pad_h = max((oh - 1) * self.stride[0] + (kh - 1) * self.dilation[0] + 1 - ih, 0)
238242
pad_w = max((ow - 1) * self.stride[1] + (kw - 1) * self.dilation[1] + 1 - iw, 0)
239243
if pad_h > 0 or pad_w > 0:
@@ -311,6 +315,7 @@ def forward(self, x):
311315
return F.max_pool2d(x, self.kernel_size, self.stride, self.padding,
312316
self.dilation, self.ceil_mode, self.return_indices)
313317

318+
314319
class MaxPool2dStaticSamePadding(nn.MaxPool2d):
315320
"""2D MaxPooling like TensorFlow's 'SAME' mode, with the given input image size.
316321
The padding mudule is calculated in construction function, then used in forward.
@@ -343,7 +348,7 @@ def forward(self, x):
343348

344349

345350
################################################################################
346-
### Helper functions for loading model params
351+
# Helper functions for loading model params
347352
################################################################################
348353

349354
# BlockDecoder: A Class for encoding and decoding BlockArgs
@@ -576,7 +581,7 @@ def get_model_params(model_name, override_params):
576581
# TODO: add the petrained weights url map of 'efficientnet-l2'
577582

578583

579-
def load_pretrained_weights(model, model_name, weights_path=None, load_fc=True, advprop=False):
584+
def load_pretrained_weights(model, model_name, weights_path=None, load_fc=True, advprop=False, verbose=True):
580585
"""Loads pretrained weights from weights path or download using url.
581586
582587
Args:
@@ -607,4 +612,5 @@ def load_pretrained_weights(model, model_name, weights_path=None, load_fc=True,
607612
['_fc.weight', '_fc.bias']), 'Missing keys when loading pretrained weights: {}'.format(ret.missing_keys)
608613
assert not ret.unexpected_keys, 'Missing keys when loading pretrained weights: {}'.format(ret.unexpected_keys)
609614

610-
print('Loaded pretrained weights for {}'.format(model_name))
615+
if verbose:
616+
print('Loaded pretrained weights for {}'.format(model_name))

examples/imagenet/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ def accuracy(output, target, topk=(1,)):
434434

435435
res = []
436436
for k in topk:
437-
correct_k = correct[:k].view(-1).float().sum(0, keepdim=True)
437+
correct_k = correct[:k].reshape(-1).float().sum(0, keepdim=True)
438438
res.append(correct_k.mul_(100.0 / batch_size))
439439
return res
440440

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
EMAIL = 'lmelaskyriazi@college.harvard.edu'
1919
AUTHOR = 'Luke'
2020
REQUIRES_PYTHON = '>=3.5.0'
21-
VERSION = '0.7.0'
21+
VERSION = '0.7.1'
2222

2323
# What packages are required for this module to be executed?
2424
REQUIRED = [

0 commit comments

Comments
 (0)