I'm not getting the correct output from model

username: Jordan_Howell
cooked: <p>Hello. I trained an autoencoder/decoder and saved the model.  I loaded the model and took the decoder portion off, in order to extract the features from the middle of the encoder.  But when i run the encoder, it states the following error;</p>
<blockquote>
<p>AttributeError: ‘tuple’ object has no attribute ‘dim’</p>
</blockquote>
<p>I thought tensors flowed through the entire object but maybe not.  How do I get tensors of features out of this encoder?  Code below:</p>
<blockquote>
<p>class DenoisingAutoencoder(nn.Module):</p>
<pre><code>def __init__(self):

    super(DenoisingAutoencoder, self).__init__()
                                                        # 32 x 32 x 3 (input)

    self.conv1e = nn.Conv2d(3, 24, 3, padding=2)        # 30 x 30 x 24
    self.conv2e = nn.Conv2d(24, 48, 3, padding=2)       # 28 x 28 x 48
    self.conv3e = nn.Conv2d(48, 96, 3, padding=2)       # 26 x 26 x 96
    self.conv4e = nn.Conv2d(96, 128, 3, padding=2)      # 24 x 24 x 128
    self.conv5e = nn.Conv2d(128, 256, 3, padding=2)     # 22 x 22 x 256
    self.mp1e   = nn.MaxPool2d(2, return_indices=True)  # 11 x 11 x 256

    self.mp1d = nn.MaxUnpool2d(2)
    self.conv5d = nn.ConvTranspose2d(256, 128, 3, padding=2)
    self.conv4d = nn.ConvTranspose2d(128, 96, 3, padding=2)
    self.conv3d = nn.ConvTranspose2d(96, 48, 3, padding=2)
    self.conv2d = nn.ConvTranspose2d(48, 24, 3, padding=2)
    self.conv1d = nn.ConvTranspose2d(24, 3, 3, padding=2)
    

def forward(self, x):
    # Encoder
    x = self.conv1e(x)
    x = F.relu(x)
    x = self.conv2e(x)
    x = F.relu(x)
    x = self.conv3e(x)
    x = F.relu(x)
    x = self.conv4e(x)
    x = F.relu(x)
    x = self.conv5e(x)
    x = F.relu(x)
    x, i = self.mp1e(x)
    
     # Decoder
    x = self.mp1d(x, i)
    x = self.conv5d(x)
    x = F.relu(x)
    x = self.conv4d(x)
    x = F.relu(x)
    x = self.conv3d(x)
    x = F.relu(x)
    x = self.conv2d(x)
    x = F.relu(x)
    x = self.conv1d(x)
    x = F.relu(x)
    
    return x
</code></pre>
</blockquote>
<p>Then I bring it back and take off the decoder:</p>
<blockquote>
<p>model = DenoisingAutoencoder()<br>
model.load_state_dict(torch.load( “C:\Users\jordan.howell\Pytorch\UW_files\roof_autoencoder.pt”))<br>
<span class="hashtag-raw">#pop</span> off the decoder<br>
new_model = nn.Sequential(*list(model.children())[:-6])<br>
model = nn.Sequential(*new_model)<br>
model.feature_vec = nn.Sequential(nn.Linear(256, 256),<br>
nn.ReLU(),<br>
nn.Linear(256, 128))<br>
model.cuda()<br>
model.eval()</p>
</blockquote>
<p>I’m not sure what I’m doing wrong.</p>

username: albanD
cooked: <p>Hi,</p>
<p>Would you have the exact stack trace of where this error comes from?</p>

username: Jordan_Howell
cooked: <blockquote>
<hr>
<p>AttributeError                            Traceback (most recent call last)<br>
 in <br>
44<br>
45         with torch.no_grad():<br>
—&gt; 46             output = model(image)<br>
47             test_image_output = output.data.cpu().numpy()<br>
48             for i in test_image_output:</p>
<p>C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py in <strong>call</strong>(self, *input, **kwargs)<br>
545             result = self._slow_forward(*input, **kwargs)<br>
546         else:<br>
 → 547             result = self.forward(*input, **kwargs)<br>
548         for hook in self._forward_hooks.values():<br>
549             hook_result = hook(self, input, result)</p>
<p>C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\container.py in forward(self, input)<br>
90     def forward(self, input):<br>
91         for module in self._modules.values():<br>
—&gt; 92             input = module(input)<br>
93         return input<br>
94</p>
<p>C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py in <strong>call</strong>(self, *input, **kwargs)<br>
545             result = self._slow_forward(*input, **kwargs)<br>
546         else:<br>
 → 547             result = self.forward(*input, **kwargs)<br>
548         for hook in self._forward_hooks.values():<br>
549             hook_result = hook(self, input, result)</p>
<p>C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\container.py in forward(self, input)<br>
90     def forward(self, input):<br>
91         for module in self._modules.values():<br>
—&gt; 92             input = module(input)<br>
93         return input<br>
94</p>
<p>C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py in <strong>call</strong>(self, *input, **kwargs)<br>
545             result = self._slow_forward(*input, **kwargs)<br>
546         else:<br>
 → 547             result = self.forward(*input, **kwargs)<br>
548         for hook in self._forward_hooks.values():<br>
549             hook_result = hook(self, input, result)</p>
<p>C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\linear.py in forward(self, input)<br>
85<br>
86     def forward(self, input):<br>
—&gt; 87         return F.linear(input, self.weight, self.bias)<br>
88<br>
89     def extra_repr(self):</p>
<p>C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\functional.py in linear(input, weight, bias)<br>
1365         - Output: :math:<code>(N, *, out\_features)</code><br>
1366     “”"<br>
 → 1367     if input.dim() == 2 and bias is not None:<br>
1368         # fused op is marginally faster<br>
1369         ret = torch.addmm(bias, input, weight.t())</p>
</blockquote>

username: albanD
cooked: <p>The problem is that the last layer of your encoder is a max pooling.<br>
In your custom forward, you do: <code>x, i = self.mp1e(x)</code> to get on one side the output and on the other the indices.<br>
But with the Sequential module, then you give the tuple of these two outputs to the Linear layer. Which is unexpected.<br>
Also you might need a reshape before the Linear to go from the <code>4D</code> inputs of convolutions to the <code>2D</code> input of a Linear layer.</p>

username: Jordan_Howell
cooked: <p>Thank you <a class="mention" href="/u/alband">@albanD</a>.  I took this notebook from a  Udemy course.  How would I flatten correctly, or is there a place in the docs to figure that out?  Also, should I not pass the indicies to the unpooling layer?</p>

username: albanD
cooked: <p>Didn’t you just said that you removed the encoder? So you removed the unpooling layer no?</p>
<p>You can see examples of this reshaping in any cnn example, <a href="https://github.com/pytorch/examples/blob/60108edfa3838a823220e16428cb5f98e8e88d53/mnist/main.py#L23" rel="nofollow noopener">this one</a> for example.</p>

username: Jordan_Howell
cooked: <p>Hi <a class="mention" href="/u/alband">@albanD</a>.  I’m still having trouble with the tensor.view command.  I thought I had it.  If I bring in the resnet-50 and pop off the last linear layer, that leaves the last layer as an adaptive average pooling layer.  With batches of 10 images. I’m getting a tensor size of (10, 2048, 1, 1,).  I understand the “10” means 10 images and the 2048 means 2048 features.  If I want a feature set of 1000 flat features, how do I reshape this?</p>
<p>I tried the following:</p>
<blockquote>
<p>CNNmodel = models.resnet50(pretrained = True)<br>
for param in CNNmodel.parameters():<br>
param.requires_grad = False<br>
model_change = nn.Sequential(*list(CNNmodel.children())[:-1])<br>
CNNmodel = nn.Sequential(*model_change)<br>
CNNmodel = nn.view(-1, 1, 1000)<br>
CNNmodel = CNNmodel.cuda()<br>
CNNmodel</p>
</blockquote>
<p>That gave an error that nn does not have a module ‘view’.  Not sure how to add a flatten layer on this.</p>

username: albanD
cooked: <p>Hi,</p>
<p><code>(10, 2048, 1, 1)</code> means that you have a batch of 10 images. with a 2048 channels and height and width of size 1.<br>
It is a very weird image , but this is the output you get from the last convolutions/spatial pooling layers.</p>
<p>To now go to Linear layers, you want a 2D Tensor of shape (batch_size x nb_features). In this case, You want: <code>out.view(-1, 2048)</code> in your case.<br>
If you want 1000 outputs in the end, you need to add other Linear layers that will do this transformation (nn.Linear(2048, 1000) for example).</p>

username: Jordan_Howell
cooked: <p>So the original resnet-50’s last linear layer is (2048, 1000). so i guess if i want that vector of the image, I can leave it, no? Run it without   Or add a out.view(-1)?</p>
<p><div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/3/d/3d35c1b8bb76c782778662f2f699aabb1d8a0a25.png" data-download-href="https://discuss.pytorch.org/uploads/default/3d35c1b8bb76c782778662f2f699aabb1d8a0a25" title="image"><img src="https://discuss.pytorch.org/uploads/default/original/3X/3/d/3d35c1b8bb76c782778662f2f699aabb1d8a0a25.png" alt="image" data-base62-sha1="8Juixa4178Fy9AxkPS2XBd7SXKR" width="690" height="352" data-dominant-color="F0F0ED"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">image</span><span class="informations">1004×513 38.5 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div></p>

username: albanD
cooked: <p>Yes you want to keep it if you need an output of size 1000.<br>
You don’t want to do <code>out.view(-1)</code>. Because it would mix the data from the different elements in the batch.</p>