How to use a state_dict pth model to classify molecular image files?

juiocollm: <p>Using windows/anaconda/spyder, python 3.8 I managed to obtain an optimized trained model which classifies thousands of molecules according to their *.png images in binding to a protein: binding (1) and non-binding(0).</p>
<p>The optimized model is kept in a pth file entitled by the DEEPScreen program I used: “AB_best_val-AB-CNNModel1-512-256-0.001-32-0.5-50-VA2-state_dict.pth” or “VA2.pth” for short.</p>
<p>I would like to use the VA2.pth optimized model to infer the 0s or 1s of hundreds of thousands of individual molecular image files already designed and located at the imgs directory (imgs / molecule1.png, molecule2.png, molecule3.png, …).</p>
<p>The only thing I got was to see some of the inside of the VA2.pth (a large collection of numbers) by using the script<br>
model = torch.load(“VA2.pth”)<br>
print(model)</p>
<p>I tried to continue using other lines of code as suggested by the web and documentation ( I am new to PyTorch), but I could not get anything else to work !</p>
<p>Could somebody help me?</p>

Dwight_Foster: <p>If you saved the state dict of the model you will still have to define the model before loading the state dict. That is not the complete model only the weights of each layer. So for example you will need to do this</p>
<pre><code class="lang-auto">class model():
   ##HERE YOU DEFINE THE MODEL ARCHITECTURE
model = model()
model.load_state_dict(torch.load("VA2.pth"))</code></pre>

juiocollm: <p>Thank you Dwight.<br>
I really appreciated.</p>
<p>I am not sure if I understood correctly.<br>
The only model I used is in the models.py inside the DEEPScreen training program.<br>
This *.py was the following :</p>
<p>import torch<br>
import torch.nn as nn<br>
import torch.nn.functional as F<br>
from operator import itemgetter</p>
<p>class CNNModel1(nn.Module):<br>
def <strong>init</strong>(self, fully_layer_1, fully_layer_2, drop_rate):<br>
super(CNNModel1, self).<strong>init</strong>()</p>
<pre><code>    self.conv1 = nn.Conv2d(3, 32, 2)
    self.bn1 = nn.BatchNorm2d(32)
    self.conv2 = nn.Conv2d(32, 64, 2)
    self.bn2 = nn.BatchNorm2d(64)
    self.conv3 = nn.Conv2d(64, 128, 2)
    self.bn3 = nn.BatchNorm2d(128)
    self.conv4 = nn.Conv2d(128, 64, 2)
    self.bn4 = nn.BatchNorm2d(64)
    self.conv5 = nn.Conv2d(64, 32, 2)
    self.bn5 = nn.BatchNorm2d(32)

    self.pool = nn.MaxPool2d(2, 2)
    self.drop_rate = drop_rate
    self.fc1 = nn.Linear(32*5*5, fully_layer_1)
    self.fc2 = nn.Linear(fully_layer_1, fully_layer_2)
    self.fc3 = nn.Linear(fully_layer_2, 2)

def forward(self, x):
    # print(x.shape)
    x = self.pool(F.relu(self.bn1(self.conv1(x))))
    # print(x.shape)
    x = self.pool(F.relu(self.bn2(self.conv2(x))))
    # print(x.shape)
    x = self.pool(F.relu(self.bn3(self.conv3(x))))
    # print(x.shape)
    x = self.pool(F.relu(self.bn4(self.conv4(x))))
    # print(x.shape)
    x = self.pool(F.relu(self.bn5(self.conv5(x))))
    # print(x.shape)

    x = x.view(-1, 32*5*5)
    x = F.dropout(F.relu(self.fc1(x)), self.drop_rate)
    x = F.dropout(F.relu(self.fc2(x)), self.drop_rate)
    x = self.fc3(x)

    return x
</code></pre>
<p>If that is the case, do you mean to use:</p>
<p>class CNNModel1(nn.Module):<br>
…include the model architecture as above…<br>
model=model()<br>
model.load_state_dict(torch.load(“VA2.pth”))</p>
<p>Assuming that is Ok, next, I supposse I have to also to include some reference to the *.png imgs they are about to be inferred (they are all files into the same directory for convinience). How?</p>
<p>Thanks again<br>
julio</p>

Dwight_Foster: <p>Yes I mean use the CNNModel1 code in *.py to recreate your model and then you will load your state dict on to that model so like this</p>
<pre><code class="lang-auto">class CNNModel1(nn.Module):
code for defining the model here. So you need the init function and forward function with all the code from *.py

model = CNNModel1(PARAMETERS)
model.load_state_dict(torch.load(“VA2.pth”))

</code></pre>
<p>where parameters are the ones you used to train your model.</p>

juiocollm: <p>I made the changes as you suggested and added at the end of the script the parameters I used for training:<br>
model = CNNModel1(target_id=“AB”, fully_layer_1=512, fully_layer_2=256, learning_rate=0.001, batch_size=32, drop_rate=0.5, n_epoch=50, experiment_name=“VA2”)<br>
model.load_state_dict(torch.load(‘VA2.pth’))</p>
<p>however I got a quick error reply on running just on the first line of the code ! as follows:</p>
<p>runfile(‘C:/- DOCKING/Macros/py/inouts/pthModels/pthModels.py’, wdir=‘C:/- DOCKING/Macros/py/inouts/pthModels’)<br>
Traceback (most recent call last):</p>
<p>File “C:- DOCKING\Macros\py\inouts\pthModels\pthModels.py”, line 15, in<br>
class CNNModel1(nn.Module):</p>
<p>TypeError: str() argument 2 must be str, not tuple</p>
<p>It surprised me because it is the same code line that is used by the training program!<br>
what is going on?</p>

Dwight_Foster: <p>I am not sure. Can you send the full code that you are using to load and define the model?</p>

juiocollm: <p>this is my pthModels.py</p>
<h1>-<em>- coding: utf-8 -</em>-</h1>
<p>“”"<br>
Created on Mon Mar 15 17:00:06 2021</p>
<p><span class="mention">@author</span>: JULIO<br>
“”"<br>
import torch<br>
from torch.utils.data import Dataset<br>
from torch.utils.data.sampler import SubsetRandomSampler, BatchSampler, SequentialSampler<br>
import torch.nn as nn<br>
import torch.nn.functional as F<br>
import torch.optim as optim<br>
from operator import itemgetter</p>
<p>class CNNModel1(nn.Module):<br>
def <strong>init</strong>(self, fully_layer_1, fully_layer_2, drop_rate):<br>
super(CNNModel1, self).<strong>init</strong>()</p>
<pre><code>    self.conv1 = nn.Conv2d(3, 32, 2)
    self.bn1 = nn.BatchNorm2d(32)
    self.conv2 = nn.Conv2d(32, 64, 2)
    self.bn2 = nn.BatchNorm2d(64)
    self.conv3 = nn.Conv2d(64, 128, 2)
    self.bn3 = nn.BatchNorm2d(128)
    self.conv4 = nn.Conv2d(128, 64, 2)
    self.bn4 = nn.BatchNorm2d(64)
    self.conv5 = nn.Conv2d(64, 32, 2)
    self.bn5 = nn.BatchNorm2d(32)

    self.pool = nn.MaxPool2d(2, 2)
    self.drop_rate = drop_rate
    self.fc1 = nn.Linear(32*5*5, fully_layer_1)
    self.fc2 = nn.Linear(fully_layer_1, fully_layer_2)
    self.fc3 = nn.Linear(fully_layer_2, 2)

def forward(self, x):
    # print(x.shape)
    x = self.pool(F.relu(self.bn1(self.conv1(x))))
    # print(x.shape)
    x = self.pool(F.relu(self.bn2(self.conv2(x))))
    # print(x.shape)
    x = self.pool(F.relu(self.bn3(self.conv3(x))))
    # print(x.shape)
    x = self.pool(F.relu(self.bn4(self.conv4(x))))
    # print(x.shape)
    x = self.pool(F.relu(self.bn5(self.conv5(x))))
    # print(x.shape)

    x = x.view(-1, 32*5*5)
    x = F.dropout(F.relu(self.fc1(x)), self.drop_rate)
    x = F.dropout(F.relu(self.fc2(x)), self.drop_rate)
    x = self.fc3(x)

    return x
</code></pre>
<p>model = CNNModel1(target_id=“AB”, fully_layer_1=512, fully_layer_2=256, learning_rate=0.001, batch_size=32, drop_rate=0.5, n_epoch=50, experiment_name=“VA2”)<br>
model.load_state_dict(torch.load(‘VA2.pth’))</p>
<h1>Initialize model</h1>
<p><span class="hashtag">#model</span> = torch.load(“VA2.pth”)<br>
<span class="hashtag">#print</span>(model)</p>

Dwight_Foster: <p>Why are you passing so many things into the CNNModel1 it only needs 3 parameters. You don’t need the target id, learning rate, batch size, n epoch, and experiment name</p>

juiocollm: <p>Sure, I attach the “pthModels.py” I am trying to develop<br>
I hope this way it will get to you…<br>
please let me know…</p>
<p>(Attachment pthModels.py is missing)</p>

juiocollm: <p>As suggested I removed the unrequired parameters. Those that were left were the fully_layer_1=512, fully_layer_2=256 and drop-rate=0.5.</p>
<p>Nevertheless the error log is still saying the same “song” :</p>
<p>File “C:- DOCKING\Macros\py\inouts\pthModels\pthModels.py”, line 15, in <br>
class CNNModel1(nn.Module):</p>
<p>TypeError: str() argument 2 must be str, not tuple</p>
<p>What is argument 2 ?</p>

Dwight_Foster: <p>Is that the full error? I am not sure what argument 2 is supposed to be.</p>

juiocollm: <p>yes is the only error detected by spyder.</p>
<p>I tried:<br>
class CNNModel1(str(nn.Module)):<br>
but it says the same error</p>
<p>I read many different things about the “TypeError: str() argument 2 must be str, not tuple” but none of them refered to “nn.Module” or “CNN”…</p>

juiocollm: <p>I also tried<br>
class CNNModel1():</p>
<p>now the same error does not appeared but it was:</p>
<p>runfile(‘C:/- DOCKING/Macros/py/inouts/pthModels/pthModels.py’, wdir=‘C:/- DOCKING/Macros/py/inouts/pthModels’)<br>
Traceback (most recent call last):</p>
<p>File “C:- DOCKING\Macros\py\inouts\pthModels\pthModels.py”, line 55, in <br>
x=CNNModel1.forward()</p>
<p>TypeError: forward() missing 2 required positional arguments: ‘self’ and ‘x’</p>
<p>does that clarifies the problem?</p>

Dwight_Foster: <p>That does actually you need to define the model first and then do the forward pass like this</p>
<pre><code class="lang-auto">model = CNNModel1(fully_layer_1, fully_layer_2, drop_rate)
model.load_state_dict(torch.load(‘VA2.pth’))
# and then the forward pass
output = model(input)
</code></pre>
<p>where you pass in the same parameters for your training into CNNModel1</p>

juiocollm: <aside class="quote no-group" data-username="Dwight_Foster" data-post="14" data-topic="114906">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/dwight_foster/48/18182_2.png" class="avatar"> Dwight_Foster:</div>
<blockquote>
<pre><code class="lang-auto">model.load_state_dict(torch.load(‘VA2.pth’))
# and then the forward pass
output = model(input)
</code></pre>
</blockquote>
</aside>
<p>I did as you suggested but I had to modify the head of the class to include<br>
class CNNModel1():<br>
def <strong>init</strong>(self, fully_layer_1=512, fully_layer_2=256, drop_rate=0.5):</p>
<p>Then I included at the end your lines of code and obtain<br>
runfile(‘C:/- DOCKING/Macros/py/inouts/pthModels/pthModels.py’, wdir=‘C:/- DOCKING/Macros/py/inouts/pthModels’)<br>
&lt;<strong>main</strong>.CNNModel1 object at 0x000000522AA4D888&gt;<br>
Traceback (most recent call last):</p>
<p>File “C:- DOCKING\Macros\py\inouts\pthModels\pthModels.py”, line 60, in <br>
model.load_state_dict(torch.load(‘VA2.pth’))</p>
<p>AttributeError: ‘CNNModel1’ object has no attribute ‘load_state_dict’</p>
<p>The most I read, the most I do not understand what I am doing, nor why ! <img src="https://discuss.pytorch.org/images/emoji/apple/frowning.png?v=12" title=":frowning:" class="emoji" alt=":frowning:" loading="lazy" width="20" height="20"></p>

Dwight_Foster: <p>Can you send me the code you use to load it. You need to define the model first like this</p>
<pre><code class="lang-auto">model = CNN1Model(PARAMETERS)
</code></pre>
<p>where the parameters are the needed for the model.</p>

juiocollm: <p>Thank you Dwight for been still there.<br>
This is my whole “best” code right now:</p>
<p>import torch<br>
import torch.nn as nn<br>
import torch.nn.functional as F<br>
from torch.utils.data import Dataset<br>
from torch.utils.data.sampler import SubsetRandomSampler, BatchSampler, SequentialSampler<br>
import torch.optim as optim<br>
from operator import itemgetter</p>
<p>class CNNModel1():#(nn.Module):<br>
def <strong>init</strong>(self, fully_layer_1=512, fully_layer_2=256, drop_rate=0.5):<br>
super(CNNModel1, self).<strong>init</strong>()</p>
<pre><code>    self.conv1 = nn.Conv2d(3, 32, 2)
    self.bn1 = nn.BatchNorm2d(32)
    self.conv2 = nn.Conv2d(32, 64, 2)
    self.bn2 = nn.BatchNorm2d(64)
    self.conv3 = nn.Conv2d(64, 128, 2)
    self.bn3 = nn.BatchNorm2d(128)
    self.conv4 = nn.Conv2d(128, 64, 2)
    self.bn4 = nn.BatchNorm2d(64)
    self.conv5 = nn.Conv2d(64, 32, 2)
    self.bn5 = nn.BatchNorm2d(32)

    self.pool = nn.MaxPool2d(2, 2)
    self.drop_rate = drop_rate
    self.fc1 = nn.Linear(32*5*5, fully_layer_1)
    self.fc2 = nn.Linear(fully_layer_1, fully_layer_2)
    self.fc3 = nn.Linear(fully_layer_2, 2)

def forward(self, x):
    # print(x.shape)
    x = self.pool(F.relu(self.bn1(self.conv1(x))))
    # print(x.shape)
    x = self.pool(F.relu(self.bn2(self.conv2(x))))
    # print(x.shape)
    x = self.pool(F.relu(self.bn3(self.conv3(x))))
    # print(x.shape)
    x = self.pool(F.relu(self.bn4(self.conv4(x))))
    # print(x.shape)
    x = self.pool(F.relu(self.bn5(self.conv5(x))))
    # print(x.shape)

    x = x.view(-1, 32*5*5)
    x = F.dropout(F.relu(self.fc1(x)), self.drop_rate)
    x = F.dropout(F.relu(self.fc2(x)), self.drop_rate)
    x = self.fc3(x)

    return x
</code></pre>
<p>model = CNNModel1(fully_layer_1=512, fully_layer_2=256, drop_rate=0.5)<br>
model.load_state_dict(torch.load(‘VA2.pth’))<br>
output = model(input)</p>
<p>Terminal answer:--------------------------------------------------------------------------<br>
runfile(‘C:/- DOCKING/Macros/py/inouts/pthModels/pthModels.py’, wdir=‘C:/- DOCKING/Macros/py/inouts/pthModels’)<br>
Traceback (most recent call last):</p>
<p>File “C:- DOCKING\Macros\py\inouts\pthModels\pthModels.py”, line 57, in <br>
model.load_state_dict(torch.load(‘VA2.pth’))</p>
<p>AttributeError: ‘CNNModel1’ object has no attribute ‘load_state_dict’</p>

Dwight_Foster: <p>Oh you need to include the nn.Module in the class definition<br>
like this</p>
<pre><code class="lang-auto">class CNNModel1(nn.Module):
</code></pre>
<p>hopefully that won’t give the error again.</p>

juiocollm: <p>thank you!<br>
however, when I did that, the old song came back again, sorry:</p>
<p>runfile(‘C:/- DOCKING/Macros/py/inouts/pthModels/pthModels.py’, wdir=‘C:/- DOCKING/Macros/py/inouts/pthModels’)<br>
Traceback (most recent call last):</p>
<p>File “C:- DOCKING\Macros\py\inouts\pthModels\pthModels.py”, line 15, in <br>
class CNNModel1(nn.Module):</p>
<p>TypeError: str() argument 2 must be str, not tuple</p>

Dwight_Foster: <p>Ok I think I see your problem. I kept overlooking it but it is so simple. When you defined the model and <strong>init</strong> function you forgot to add the two underscores on each side like this:</p>
<pre><code class="lang-auto">class CNNModel1(nn.Module):  # (nn.Module):

    def __init__(self, fully_layer_1=512, fully_layer_2=256,  drop_rate-0.5):
        super(CNNModel1, self).__init__()
</code></pre>
<p>hopefully that will fix it.</p>