Repository navigation
fix(nets): thread ResNet norm/act into residual blocks and guard non-affine init #9028
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
928f3af
7722c9a
f57cc91
5f3e2b0
f2f990d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -211,6 +211,9 @@ class ResNet(nn.Module): | |
| bias_downsample: whether to use bias term in the downsampling block when `shortcut_type` is 'B', default to `True`. | ||
| act: activation type and arguments. Defaults to relu. | ||
| norm: feature normalization type and arguments. Defaults to batch norm. | ||
| block_norm_act: whether the residual blocks and their downsampling layers also use `act` and `norm`. | ||
| Defaults to `False`, in which case only the first convolution uses them and the blocks keep | ||
| ReLU and batch norm, matching previous versions. | ||
|
|
||
| """ | ||
|
|
||
|
|
@@ -231,6 +234,7 @@ def __init__( | |
| bias_downsample: bool = True, # for backwards compatibility (also see PR #5477) | ||
| act: str | tuple = ("relu", {"inplace": True}), | ||
| norm: str | tuple = "batch", | ||
| block_norm_act: bool = False, | ||
| ) -> None: | ||
| super().__init__() | ||
|
|
||
|
|
@@ -271,19 +275,29 @@ def __init__( | |
| self.bn1 = norm_layer | ||
| self.act = get_act_layer(name=act) | ||
| self.maxpool = pool_type(kernel_size=3, stride=2, padding=1) | ||
| self.layer1 = self._make_layer(block, block_inplanes[0], layers[0], spatial_dims, shortcut_type) | ||
| self.layer2 = self._make_layer(block, block_inplanes[1], layers[1], spatial_dims, shortcut_type, stride=2) | ||
| self.layer3 = self._make_layer(block, block_inplanes[2], layers[2], spatial_dims, shortcut_type, stride=2) | ||
| self.layer4 = self._make_layer(block, block_inplanes[3], layers[3], spatial_dims, shortcut_type, stride=2) | ||
| block_kwargs: dict = {"norm": norm, "act": act} if block_norm_act else {} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| self.layer1 = self._make_layer(block, block_inplanes[0], layers[0], spatial_dims, shortcut_type, **block_kwargs) | ||
| self.layer2 = self._make_layer( | ||
| block, block_inplanes[1], layers[1], spatial_dims, shortcut_type, stride=2, **block_kwargs | ||
| ) | ||
| self.layer3 = self._make_layer( | ||
| block, block_inplanes[2], layers[2], spatial_dims, shortcut_type, stride=2, **block_kwargs | ||
| ) | ||
| self.layer4 = self._make_layer( | ||
| block, block_inplanes[3], layers[3], spatial_dims, shortcut_type, stride=2, **block_kwargs | ||
| ) | ||
| self.avgpool = avgp_type(block_avgpool[spatial_dims]) | ||
| self.fc = nn.Linear(block_inplanes[3] * block.expansion, num_classes) if feed_forward else None | ||
|
|
||
| for m in self.modules(): | ||
| if isinstance(m, conv_type): | ||
| nn.init.kaiming_normal_(torch.as_tensor(m.weight), mode="fan_out", nonlinearity="relu") | ||
| elif isinstance(m, type(norm_layer)): | ||
| nn.init.constant_(torch.as_tensor(m.weight), 1) | ||
| nn.init.constant_(torch.as_tensor(m.bias), 0) | ||
| # non-affine norm layers (e.g. instance/layer norm defaults) have no weight/bias | ||
| if m.weight is not None: | ||
| nn.init.constant_(torch.as_tensor(m.weight), 1) | ||
| if m.bias is not None: | ||
| nn.init.constant_(torch.as_tensor(m.bias), 0) | ||
| elif isinstance(m, nn.Linear): | ||
| nn.init.constant_(torch.as_tensor(m.bias), 0) | ||
|
|
||
|
|
@@ -302,6 +316,7 @@ def _make_layer( | |
| shortcut_type: str, | ||
| stride: int = 1, | ||
| norm: str | tuple = "batch", | ||
| act: str | tuple = ("relu", {"inplace": True}), | ||
| ) -> nn.Sequential: | ||
| conv_type: Callable = Conv[Conv.CONV, spatial_dims] | ||
|
|
||
|
|
@@ -333,13 +348,14 @@ def _make_layer( | |
| spatial_dims=spatial_dims, | ||
| stride=stride, | ||
| downsample=downsample, | ||
| act=act, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| norm=norm, | ||
| ) | ||
| ] | ||
|
|
||
| self.in_planes = planes * block.expansion | ||
| for _i in range(1, blocks): | ||
| layers.append(block(self.in_planes, planes, spatial_dims=spatial_dims, norm=norm)) | ||
| layers.append(block(self.in_planes, planes, spatial_dims=spatial_dims, act=act, norm=norm)) | ||
|
|
||
| return nn.Sequential(*layers) | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Script executed:
Repository: Project-MONAI/MONAI
Length of output: 18044
Fix the
block_norm_actdocstring: downsampling layers usenormonly.The docstring says
block_norm_actmakes the downsampling layers useact. The shortcut-B downsample is built with only a convolution andnorm, soactis never applied there. Reword the description so it matches the constructed model.📝 Suggested docstring fix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aymuos15 this and the following comments perhaps should be addressed?