Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
d9c6fc6
add a register and a base encoder class for flexible unet.
binliunls Aug 31, 2022
c66f5fd
Merge branch 'Project-MONAI:dev' into 5011-flexible-unet
binliunls Sep 2, 2022
2fce71c
Merge branch 'Project-MONAI:dev' into 5011-flexible-unet
binliunls Sep 6, 2022
01103a9
Merge branch 'Project-MONAI:dev' into 5011-flexible-unet
binliunls Sep 6, 2022
f8ccee2
add first version encoder.
binliunls Sep 6, 2022
0d6470c
add first version registry
binliunls Sep 6, 2022
d0e01cc
add encoder and registry to __init__
binliunls Sep 6, 2022
b74bfa9
Merge branch 'Project-MONAI:dev' into 5011-flexible-unet
binliunls Oct 8, 2022
86d3d91
Merge branch 'Project-MONAI:dev' into 5011-flexible-unet
binliunls Oct 9, 2022
dc0593d
add efficient as encoder for flexible unet
binliunls Oct 9, 2022
5e6e66d
fix the type hints for BasicEncoder
binliunls Oct 9, 2022
fe719a2
move registry to this file and update the flexible unet for convenien…
binliunls Oct 9, 2022
a33bde3
delete some legacy code
binliunls Oct 9, 2022
c5804a5
fix the wrong var name
binliunls Oct 9, 2022
ad6ba66
fix type hints issue
binliunls Oct 10, 2022
991c6bb
mv encoder to blocks dir
binliunls Oct 10, 2022
2e9185a
remove registry file
binliunls Oct 10, 2022
b3384a5
change function name of BasicEncoder
binliunls Oct 10, 2022
e2dc003
add comments
binliunls Oct 10, 2022
d0edb6c
add backbone to nets init
binliunls Oct 10, 2022
9dc07fd
update comment
binliunls Oct 10, 2022
e3c9cc1
update comment of efficientnet
binliunls Oct 10, 2022
8bb63d5
update comment and add assertion for encoder parameters
binliunls Oct 10, 2022
0f7097a
Merge branch 'dev' into 5011-flexible-unet
binliunls Oct 12, 2022
6f44b78
add resnet encoder to unitest
binliunls Oct 13, 2022
2538541
fix test case code format
binliunls Oct 13, 2022
18e6559
Merge branch 'Project-MONAI:dev' into 5011-flexible-unet
binliunls Oct 14, 2022
b42eb01
Merge branch '5011-flexible-unet' of https://github.com/binliunls/MON…
binliunls Oct 14, 2022
46a5a50
add raising NotImplementedError in abstractmethod
binliunls Oct 14, 2022
1010ce8
update method name of BasicEncoder and corresponding files
binliunls Oct 14, 2022
56b3332
change assert logic in flexible unet to raise error
binliunls Oct 14, 2022
fc2f40a
fix the fstring problem
binliunls Oct 14, 2022
8015536
changeflexible unet unitest according to basic encoder.
binliunls Oct 14, 2022
d2c407d
fix the string too long problem
binliunls Oct 14, 2022
79d7483
fix the long string bug in windows
binliunls Oct 14, 2022
7fae98c
Merge branch 'Project-MONAI:dev' into 5011-flexible-unet
binliunls Oct 19, 2022
b7e3363
change BasicEncoder to BaseEncoder and fix a typo problem
binliunls Oct 19, 2022
81eb1c9
fix efficientnet string error
binliunls Oct 19, 2022
ad55efa
add string type input to Register in FlexibleUnet
binliunls Oct 19, 2022
c9ba58b
Merge branch 'dev' into 5011-flexible-unet
binliunls Oct 20, 2022
0fc2e3f
fix long string in flexible_unet
binliunls Oct 20, 2022
40e0090
Merge branch '5011-flexible-unet' of https://github.com/binliunls/MON…
binliunls Oct 20, 2022
d981093
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 20, 2022
77bcc3a
[MONAI] code formatting
monai-bot Oct 20, 2022
adac4eb
fix the format problem
binliunls Oct 20, 2022
9c2216d
Merge branch '5011-flexible-unet' of https://github.com/binliunls/MON…
binliunls Oct 20, 2022
f2f9170
add the 2x output constrain to docstring of flexibleunet and its regi…
binliunls Oct 20, 2022
92bb7a2
modify name of base encoder methods, flexible unet register and flexi…
binliunls Oct 20, 2022
a1375c2
add a alias name for FlexibleUNet
binliunls Oct 20, 2022
3942fa6
change name of flexible unet backbon
binliunls Oct 20, 2022
c2af31a
Merge branch 'dev' into 5011-flexible-unet
wyli Oct 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions monai/networks/blocks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from .dints_block import ActiConvNormBlock, FactorizedIncreaseBlock, FactorizedReduceBlock, P3DActiConvNormBlock
from .downsample import MaxAvgPool
from .dynunet_block import UnetBasicBlock, UnetOutBlock, UnetResBlock, UnetUpBlock, get_output_padding, get_padding
from .encoder import BaseEncoder
from .fcn import FCN, GCN, MCFCN, Refine
from .feature_pyramid_network import ExtraFPNBlock, FeaturePyramidNetwork, LastLevelMaxPool, LastLevelP6P7
from .localnet_block import LocalNetDownSampleBlock, LocalNetFeatureExtractorBlock, LocalNetUpSampleBlock
Expand Down
84 changes: 84 additions & 0 deletions monai/networks/blocks/encoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Copyright (c) MONAI Consortium
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from abc import ABCMeta, abstractmethod
from typing import Dict, List, Tuple

__all__ = ["BaseEncoder"]


class BaseEncoder(metaclass=ABCMeta):
Comment thread
Nic-Ma marked this conversation as resolved.
"""
Abstract class defines interface of encoders in flexible unet.
Encoders in flexible unet must derive from this class. Each interface method
should return a list containing relative information about a series of newtworks
defined by encoder. For example, the efficient-net encoder implement 10 basic
network structures in one encoder. When calling `get_encoder_name_string_list`
function, a string list like ["efficientnet-b0", "efficientnet-b1" ... "efficientnet-l2"]
should be returned.
"""

@classmethod
@abstractmethod
def get_encoder_parameters(cls) -> List[Dict]:
"""
Get parameter list to initialize encoder networks.
Each parameter dict must have `spatial_dims`, `in_channels`
and `pretrained` parameters.
The reason that this function should return a list is that a
series of encoders can be implemented by one encoder class
given different initialization parameters. Each parameter dict
in return list should be able to initialize a unique encoder.
"""
raise NotImplementedError

@classmethod
@abstractmethod
def num_channels_per_output(cls) -> List[Tuple[int, ...]]:
"""
Get number of output features' channels.
The reason that this function should return a list is that a
series of encoders can be implemented by one encoder class
given different initialization parameters. And it is possible
that different encoders have different output feature map
channels. Therefore a list of output feature map channel tuples
corresponding to each encoder should be returned by this method.
"""
raise NotImplementedError

@classmethod
@abstractmethod
def num_outputs(cls) -> List[int]:
"""
Get number of outputs of encoder.
The reason that this function should return a list is that a
series of encoders can be implemented by one encoder class
given different initialization parameters. And it is possible
that different encoders have different output feature numbers.
Therefore a list of output feature numbers corresponding to
each encoder should be returned by this method.
"""
raise NotImplementedError

@classmethod
@abstractmethod
def get_encoder_names(cls) -> List[str]:
"""
Get the name string of encoders which will be used to initialize
flexible unet.
The reason that this function should return a list is that a
series of encoders can be implemented by one encoder class
given different initialization parameters. And a name string is
the key to each encoder in flexible unet backbone registry.
Therefore this method should return every encoder name that needs
to be registed in flexible unet.
"""
raise NotImplementedError
16 changes: 14 additions & 2 deletions monai/networks/nets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@
EfficientNet,
EfficientNetBN,
EfficientNetBNFeatures,
EfficientNetEncoder,
drop_connect,
get_efficientnet_image_size,
)
from .flexible_unet import FlexibleUNet
from .flexible_unet import FLEXUNET_BACKBONE, FlexibleUNet, FlexUNet, FlexUNetEncoderRegister
from .fullyconnectednet import FullyConnectedNet, VarFullyConnectedNet
from .generator import Generator
from .highresnet import HighResBlock, HighResNet
Expand All @@ -50,7 +51,18 @@
from .netadapter import NetAdapter
from .regressor import Regressor
from .regunet import GlobalNet, LocalNet, RegUNet
from .resnet import ResNet, resnet10, resnet18, resnet34, resnet50, resnet101, resnet152, resnet200
from .resnet import (
ResNet,
ResNetBlock,
ResNetBottleneck,
resnet10,
resnet18,
resnet34,
resnet50,
resnet101,
resnet152,
resnet200,
)
from .segresnet import SegResNet, SegResNetVAE
from .segresnet_ds import SegResNetDS
from .senet import (
Expand Down
110 changes: 87 additions & 23 deletions monai/networks/nets/efficientnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
import operator
import re
from functools import reduce
from typing import List, NamedTuple, Optional, Tuple, Type, Union
from typing import Dict, List, NamedTuple, Optional, Tuple, Type, Union

import torch
from torch import nn
from torch.utils import model_zoo

from monai.networks.blocks import BaseEncoder
from monai.networks.layers.factories import Act, Conv, Pad, Pool
from monai.networks.layers.utils import get_norm_layer
from monai.utils.module import look_up_option
Expand All @@ -30,6 +31,7 @@
"drop_connect",
"EfficientNetBNFeatures",
"BlockArgs",
"EfficientNetEncoder",
]

efficientnet_params = {
Expand Down Expand Up @@ -528,11 +530,8 @@ def __init__(

# check if model_name is valid model
if model_name not in efficientnet_params.keys():
raise ValueError(
"invalid model_name {} found, must be one of {} ".format(
model_name, ", ".join(efficientnet_params.keys())
)
)
model_name_string = ", ".join(efficientnet_params.keys())
raise ValueError(f"invalid model_name {model_name} found, must be one of {model_name_string} ")

# get network parameters
weight_coeff, depth_coeff, image_size, dropout_rate, dropconnect_rate = efficientnet_params[model_name]
Expand Down Expand Up @@ -588,11 +587,8 @@ def __init__(

# check if model_name is valid model
if model_name not in efficientnet_params.keys():
raise ValueError(
"invalid model_name {} found, must be one of {} ".format(
model_name, ", ".join(efficientnet_params.keys())
)
)
model_name_string = ", ".join(efficientnet_params.keys())
raise ValueError(f"invalid model_name {model_name} found, must be one of {model_name_string} ")

# get network parameters
weight_coeff, depth_coeff, image_size, dropout_rate, dropconnect_rate = efficientnet_params[model_name]
Expand Down Expand Up @@ -638,6 +634,80 @@ def forward(self, inputs: torch.Tensor):
return features


class EfficientNetEncoder(EfficientNetBNFeatures, BaseEncoder):
"""
Wrap the original efficientnet to an encoder for flexible-unet.
"""

backbone_names = [
"efficientnet-b0",
"efficientnet-b1",
"efficientnet-b2",
"efficientnet-b3",
"efficientnet-b4",
"efficientnet-b5",
"efficientnet-b6",
"efficientnet-b7",
"efficientnet-b8",
"efficientnet-l2",
]

@classmethod
def get_encoder_parameters(cls) -> List[Dict]:
"""
Get the initialization parameter for efficientnet backbones.
"""
parameter_list = []
for backbone_name in cls.backbone_names:
parameter_list.append(
{
"model_name": backbone_name,
"pretrained": True,
"progress": True,
"spatial_dims": 2,
"in_channels": 3,
"num_classes": 1000,
"norm": ("batch", {"eps": 1e-3, "momentum": 0.01}),
"adv_prop": "ap" in backbone_name,
}
)
return parameter_list

@classmethod
def num_channels_per_output(cls) -> List[Tuple[int, ...]]:
"""
Get number of efficientnet backbone output feature maps' channel.
"""
return [
(16, 24, 40, 112, 320),
(16, 24, 40, 112, 320),
(16, 24, 48, 120, 352),
(24, 32, 48, 136, 384),
(24, 32, 56, 160, 448),
(24, 40, 64, 176, 512),
(32, 40, 72, 200, 576),
(32, 48, 80, 224, 640),
(32, 56, 88, 248, 704),
(72, 104, 176, 480, 1376),
]

@classmethod
def num_outputs(cls) -> List[int]:
"""
Get number of efficientnet backbone output feature maps.
Since every backbone contains the same 5 output feature maps,
the number list should be `[5] * 10`.
"""
return [5] * 10

@classmethod
def get_encoder_names(cls) -> List[str]:
"""
Get names of efficient backbone.
"""
return cls.backbone_names


def get_efficientnet_image_size(model_name: str) -> int:
"""
Get the input image size for a given efficientnet model.
Expand All @@ -651,9 +721,8 @@ def get_efficientnet_image_size(model_name: str) -> int:
"""
# check if model_name is valid model
if model_name not in efficientnet_params.keys():
raise ValueError(
"invalid model_name {} found, must be one of {} ".format(model_name, ", ".join(efficientnet_params.keys()))
)
model_name_string = ", ".join(efficientnet_params.keys())
raise ValueError(f"invalid model_name {model_name} found, must be one of {model_name_string} ")

# return input image size (all dims equal so only need to return for one dim)
_, _, res, _, _ = efficientnet_params[model_name]
Expand Down Expand Up @@ -927,15 +996,10 @@ def to_string(self):
A string notation of BlockArgs object arguments.
Example: "r1_k3_s11_e1_i32_o16_se0.25_noskip".
"""
string = "r{}_k{}_s{}{}_e{}_i{}_o{}_se{}".format(
self.num_repeat,
self.kernel_size,
self.stride,
self.stride,
self.expand_ratio,
self.input_filters,
self.output_filters,
self.se_ratio,
string = (
f"r{self.num_repeat}_k{self.kernel_size}_s{self.stride}{self.stride}"
f"_e{self.expand_ratio}_i{self.input_filters}_o{self.output_filters}"
f"_se{self.se_ratio}"
)

if not self.id_skip:
Expand Down
Loading