pytorch-summary
pytorch-summary copied to clipboard
Prints twice all layers
Hi,
The summary
module seems to behave weirdly on my model. The function outputs all my layers twice in duplicate fashion.
The code is the following:
import torch
import torch.nn as nn
from torchsummary import summary
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
K = 69
L = 1000
self.group1 = nn.Sequential(
nn.Conv3d(3, K, kernel_size=3,padding=(1,1,1)),
nn.LeakyReLU()
)
self.group2 = nn.Sequential(
nn.Conv3d(K, L, kernel_size=4, padding=(1,1,1)),
nn.MaxPool3d(2, stride=2,ceil_mode=True),
nn.ReLU()
)
self._features = nn.Sequential(
self.group1,
self.group2
)
def forward(self,x):
out = self._features(x)
return out
if '__main__' == __name__:
model = Model()
inp = (3, 30, 30, 30)
summary(model, inp, device='cpu')
The output is the following:
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv3d-1 [-1, 69, 30, 30, 30] 5,658
Conv3d-2 [-1, 69, 30, 30, 30] 5,658
LeakyReLU-3 [-1, 69, 30, 30, 30] 0
LeakyReLU-4 [-1, 69, 30, 30, 30] 0
Conv3d-5 [-1, 1000, 29, 29, 29] 4,417,000
Conv3d-6 [-1, 1000, 29, 29, 29] 4,417,000
MaxPool3d-7 [-1, 1000, 15, 15, 15] 0
MaxPool3d-8 [-1, 1000, 15, 15, 15] 0
ReLU-9 [-1, 1000, 15, 15, 15] 0
ReLU-10 [-1, 1000, 15, 15, 15] 0
================================================================
Total params: 8,845,316
Trainable params: 8,845,316
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.31
Forward/backward pass size (MB): 532.00
Params size (MB): 33.74
Estimated Total Size (MB): 566.05
----------------------------------------------------------------
As you can see in the self.group1()
I have one nn.Conv3d()
. However, in the output I get Conv3d-1
and Conv3d-2
for that layer.
When model.apply(register_hook)
runs it seems to already append twice the number of module.register_forward_hook(hook)
expected in the hooks
list.
Any clues about what is happening?
Thanks, Matthias
@sksq96 Any clues? Thanks
I'm not entirely sure what that is happening, but you can get around the issue with this model structure instead. Notice that you no longer use the attributes group1 and group2. It does mean its not as neatly structured, but I wonder if its something wrong with what is being returned by register_forward_hook(hook))
. Not entirely sure though.
self._features = nn.Sequential(
nn.Sequential(
nn.Conv3d(3, K, kernel_size=3,padding=(1,1,1)),
nn.LeakyReLU()
),
nn.Sequential(
nn.Conv3d(K, L, kernel_size=4, padding=(1,1,1)),
nn.MaxPool3d(2, stride=2,ceil_mode=True),
nn.ReLU()
)
)
@mangotree3
This is not a pytorch-sumamry
's bug.
This is due to the implementation of PyTorch, and your unintended results are that self.group1
and self.group2
are declared as instance variables of Model
.
Actually, when I change self.group1
and self.group2
to group1
and group2
and execute, I get the intended results:
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv3d-1 [-1, 69, 30, 30, 30] 5,658
LeakyReLU-2 [-1, 69, 30, 30, 30] 0
Conv3d-3 [-1, 1000, 29, 29, 29] 4,417,000
MaxPool3d-4 [-1, 1000, 15, 15, 15] 0
ReLU-5 [-1, 1000, 15, 15, 15] 0
================================================================
Total params: 4,422,658
Trainable params: 4,422,658
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.31
Forward/backward pass size (MB): 266.00
Params size (MB): 16.87
Estimated Total Size (MB): 283.18
----------------------------------------------------------------
I got the same issue, not a big problem, but definitely a bug. I have a model from Colab which I am not running on Google Cloud, changed noting on the notebook, but also got it to print twice.
@luisdiaz1997
Hmmm, can you share the code?
https://github.com/luisdiaz1997/DataScienceCourse/blob/master/Week_10_solutions.ipynb In Colab it only shows once, but in my cloud it shows twice, is worth to note that in Colab I did not install it from here, in my cloud I had to. It doesn't show up twice if I do
some_var = summary(model, (some_shape) ) if I save it to a variable it only prints once. I assume there is a print() inside summary()
I assume there is a print() inside summary()
It is true that there is a print()
in summary()
, but since summary()
has no return value, I cannot understand its behavior:/
Thanks everyone for your comments and answers. I agree with @skmatz there not much one can do other than adapt the model's code. The package is just built on top of pytorch and one has to work with the tools they give you... I confirm that the problem effectively lies in having a double self
assignment of the model's parts in the __init__()
.
As mentioned by @Naireen, this works:
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
K = 69
L = 1000
self._features = nn.Sequential(
nn.Sequential(
nn.Conv3d(3, K, kernel_size=3,padding=(1,1,1)),
nn.LeakyReLU()
)
nn.Sequential(
nn.Conv3d(K, L, kernel_size=4, padding=(1,1,1)),
nn.MaxPool3d(2, stride=2,ceil_mode=True),
nn.ReLU()
)
)
def forward(self,x):
out = self._features(x)
return out
Alternatively this also works:
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
K = 69
L = 1000
self.group1 = nn.Sequential(
nn.Conv3d(3, K, kernel_size=3,padding=(1,1,1)),
nn.LeakyReLU()
)
self.group2 = nn.Sequential(
nn.Conv3d(K, L, kernel_size=4, padding=(1,1,1)),
nn.MaxPool3d(2, stride=2,ceil_mode=True),
nn.ReLU()
)
def forward(self,x):
out = self.group1(x)
out = self.group2(out)
return out
However, this doesn't work (prints double) because you have the two groups of elements (the "groups" and the "features") in the __init__
with one nested into the other and they seem to both call the hook
at initialization:
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
K = 69
L = 1000
self.group1 = nn.Sequential(
nn.Conv3d(3, K, kernel_size=3,padding=(1,1,1)),
nn.LeakyReLU()
)
self.group2 = nn.Sequential(
nn.Conv3d(K, L, kernel_size=4, padding=(1,1,1)),
nn.MaxPool3d(2, stride=2,ceil_mode=True),
nn.ReLU()
)
self._features = nn.Sequential(
self.group1,
self.group2
)
def forward(self,x):
out = self._features(x)
return out