RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [200]] is at version 2; expected version 1 instead. Hint: enable anomaly detection to find the operation that failed to comput

mahmoud_ramadan_muha: <p>Traceback (most recent call last):<br>
File “E:\predict_ddi-master\predict_ddi-master\src\run.py”, line 42, in <br>
model.fit(dataloader, i)<br>
File “E:\predict_ddi-master\predict_ddi-master\src\model.py”, line 94, in fit<br>
DNN_loss.backward()<br>
File “C:\Users\mahmoud\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\torch_tensor.py”, line 488, in backward<br>
torch.autograd.backward(<br>
File “C:\Users\mahmoud\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\torch\autograd_<em>init</em>_.py”, line 197, in backward<br>
Variable._execution_engine.run_backward(  # Calls into the C++ engine to run the backward pass<br>
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [200]] is at version 2; expected version 1 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).</p>
<p>run.py code</p>
<pre><code class="lang-auto">import torch
import torch.nn as nn
import numpy as np
import pandas as pd
from sklearn.model_selection import RepeatedStratifiedKFold
import json

from model import build_model
from utils import index_data, convert_tensor

SS_mat = pd.read_pickle('../data/structural_similarity_matrix.pkl')
TS_mat = pd.read_pickle('../data/target_similarity_matrix.pkl')
GS_mat = pd.read_pickle('../data/GO_similarity_matrix.pkl')

mlb, _, idx2label, drugPair2effectIdx = index_data()
pd.to_pickle(mlb, '../data/mlb.pkl')
pd.to_pickle(idx2label, '../data/idx2label.pkl')
    
x_idx = []
y_idx = []
for k, v in drugPair2effectIdx.items():
    x_idx.append(k)
    y_idx.append(v)
x_idx, y_idx = np.array(x_idx), np.array(y_idx)

with open('../data/hyperparameter.json') as fp:
    hparam = json.load(fp)

kf = RepeatedStratifiedKFold(n_splits=hparam['n_splits'], n_repeats=hparam['n_repeats'], random_state=2020)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

for i, (train_idx, test_idx) in enumerate(kf.split(x_idx, y_idx)):    
    x_train = x_idx[train_idx]
    y_train = y_idx[train_idx]    
    
    SS, TS, GS, y = convert_tensor(x_train, y_train, SS_mat, TS_mat, GS_mat, mlb, idx2label)
    dataset = torch.utils.data.TensorDataset(SS, TS, GS, y)
    dataloader = torch.utils.data.DataLoader(dataset, batch_size=256, shuffle=True)
    
    model = build_model(hparam)
    model.to(device)
    model.fit(dataloader, i)
        
    x_test = x_idx[test_idx]
    y_test = y_idx[test_idx]
    pd.to_pickle([x_test, y_test], model.path+'test_data.pkl')
    del x_test, y_test
    
</code></pre>
<p>model.py code</p>
<pre><code class="lang-auto">import torch
import torch.nn as nn
import os
import pandas as pd
import numpy as np
from math import ceil

class build_model(nn.Module):
    def __init__(self, hyperparameter):
        super(build_model, self).__init__()       
        
        input_size = hyperparameter['input_size']
        output_size = hyperparameter['output_size']
        code_size = hyperparameter['code_size']
        AE_lr = hyperparameter['AE_lr']
        DNN_lr = hyperparameter['DNN_lr']
        drop_rate = hyperparameter['drop_rate']
        
        self.epoch = hyperparameter['epoch']
        self.n_repeats = hyperparameter['n_repeats']
        self.n_splits = hyperparameter['n_splits']
        self.save_path = hyperparameter['save_path']
        self.patience = hyperparameter['patience']
        
        self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
        
        self.encoder1 = self.build_encoder(input_size, code_size, drop_rate)
        self.decoder1 = self.build_decoder(input_size, code_size)
        AE_params1 = list(self.encoder1.parameters()) + list(self.decoder1.parameters())
        self.AE_opt1 = torch.optim.RMSprop(AE_params1, lr=AE_lr)
        
        self.encoder2 = self.build_encoder(input_size, code_size, drop_rate)
        self.decoder2 = self.build_decoder(input_size, code_size)
        AE_params2 = list(self.encoder2.parameters()) + list(self.decoder2.parameters())
        self.AE_opt2 = torch.optim.RMSprop(AE_params2, lr=AE_lr)
        
        self.encoder3 = self.build_encoder(input_size, code_size, drop_rate)
        self.decoder3 = self.build_decoder(input_size, code_size)
        AE_params3 = list(self.encoder3.parameters()) + list(self.decoder3.parameters())
        self.AE_opt3 = torch.optim.RMSprop(AE_params3, lr=AE_lr)
        
        self.AE_criterion = nn.MSELoss()        
        
        self.DNN = self.build_DNN(code_size*3, output_size, drop_rate)
        DNN_params = list(self.encoder1.parameters()) + list(self.encoder2.parameters()) + list(self.encoder3.parameters()) + list(self.DNN.parameters())        
        self.DNN_opt = torch.optim.Adam(DNN_params, lr=DNN_lr)
        
        self.DNN_criterion = nn.BCEWithLogitsLoss()
        
    
    def forward(self, x1, x2, x3):
        x1 = self.encoder1(x1)
        x1_de = self.decoder1(x1)
        
        x2 = self.encoder2(x2)
        x2_de = self.decoder2(x2)
        
        x3 = self.encoder3(x3)
        x3_de = self.decoder3(x3)
        
        x_dnn = torch.cat((x1, x2, x3), 1)
        pred = self.DNN(x_dnn)
        
        return x1_de, x2_de, x3_de, pred
    
    def fit(self, dataloader, repeat):        
        n = ceil(len(dataloader.dataset)/dataloader.batch_size)
        loss_per_epoch = [] # ['DNN', 'SSP', 'TSP', 'GSP']        
        previous = -1
        for i in range(1, self.epoch+1):
            dnn, ae1, ae2, ae3, j = 0, 0, 0, 0, 1
            
            for x1, x2, x3, y in dataloader:
                x1, x2, x3, y = x1.to(self.device), x2.to(self.device), x3.to(self.device), y.to(self.device)
                o1, o2, o3, pred = self(x1, x2, x3)
                
                self.AE_opt1.zero_grad()
                AE_loss1 = self.AE_criterion(o1, x1) 
                AE_loss1.backward(retain_graph=True)
                self.AE_opt1.step()
                
                self.AE_opt2.zero_grad()
                AE_loss2 = self.AE_criterion(o2, x2)
                AE_loss2.backward(retain_graph=True)
                self.AE_opt2.step()
                
                self.AE_opt3.zero_grad()
                AE_loss3 = self.AE_criterion(o3, x3)
                AE_loss3.backward(retain_graph=True)
                self.AE_opt3.step()
                
                self.DNN_opt.zero_grad()
                DNN_loss = self.DNN_criterion(pred, y)
                DNN_loss.backward()
                self.DNN_opt.step()
                
                tmp_loss = list(map(lambda x: round(float(x), 6), [DNN_loss, AE_loss1, AE_loss2, AE_loss3]))
                dnn += tmp_loss[0]
                ae1 += tmp_loss[1]
                ae2 += tmp_loss[2]
                ae3 += tmp_loss[3]
                
                if j % 50 == 0:
                    print(f'Repeat {repeat+1}/{self.n_repeats*self.n_splits}  Epoch {i}/{self.epoch}  Iter {j}/{n} \n Loss:  DNN {dnn/j:.6f}  SSP {ae1/j:.6f}  TSP {ae2/j:.6f}  GSP {ae3/j:.6f}')
                    print()
                    
                j += 1
                
            j -= 1
            print(f'Repeat {repeat+1}/{self.n_repeats*self.n_splits}  Epoch {i}/{self.epoch}  Iter {j}/{n} \n Loss:  DNN {dnn/j:.6f}  SSP {ae1/j:.6f}  TSP {ae2/j:.6f}  GSP {ae3/j:.6f}')
            print()
            loss_per_epoch.append(list(map(lambda x: x/(j), [dnn, ae1, ae2, ae3])))            
            
            
            if len(loss_per_epoch) &gt; self.patience:
                sum_loss = np.sum(np.array(loss_per_epoch), 1)
                current = np.argmin(sum_loss)
                
                if previous != current:
                    previous = current
                    self.save_model(repeat, loss_per_epoch)
                    
                elif (previous == current) and (previous + self.patience == len(loss_per_epoch)):
                    print('===================Early Stopping===================')
                    break
                                            
    
    def build_encoder(self, input_size, code_size, drop_rate):        
        encoder = nn.Sequential(            
            nn.Linear(input_size, 1000),
            nn.BatchNorm1d(1000),
            nn.Dropout(p=drop_rate, inplace=True),
            nn.ReLU(True),            
            nn.Linear(1000, code_size),
            nn.BatchNorm1d(code_size),
            nn.Dropout(p=drop_rate, inplace=True),
            nn.ReLU(True))
        
        return encoder
    
    def build_decoder(self, input_size, code_size):
        decoder = nn.Sequential(
            nn.Linear(code_size, 1000),
            nn.BatchNorm1d(1000),
            nn.ReLU(True),            
            nn.Linear(1000, input_size),            
            nn.Sigmoid())
        
        return decoder
    
    def build_DNN(self, input_size, output_size, drop_rate):
        DNN = nn.Sequential(            
            nn.Linear(input_size, 2000),
            nn.BatchNorm1d(2000),
            nn.Dropout(p=drop_rate, inplace=True),
            nn.ReLU(True),            
            nn.Linear(2000, 2000),
            nn.BatchNorm1d(2000),
            nn.Dropout(p=drop_rate, inplace=True),
            nn.ReLU(True),
            nn.Linear(2000, 2000),
            nn.BatchNorm1d(2000),
            nn.Dropout(p=drop_rate, inplace=True),
            nn.ReLU(True),
            nn.Linear(2000, 2000),
            nn.BatchNorm1d(2000),
            nn.Dropout(p=drop_rate, inplace=True),
            nn.ReLU(True),
            nn.Linear(2000, 2000),
            nn.BatchNorm1d(2000),
            nn.Dropout(p=drop_rate, inplace=True),
            nn.ReLU(True),
            nn.Linear(2000, 2000),
            nn.BatchNorm1d(2000),
            nn.Dropout(p=drop_rate, inplace=True),
            nn.ReLU(True),
            nn.Linear(2000, 2000),
            nn.BatchNorm1d(2000),
            nn.Dropout(p=drop_rate, inplace=True),
            nn.ReLU(True),
            nn.Linear(2000, output_size))
        
        return DNN
    
    
    def save_model(self, repeat, loss_per_epoch):
        self.path = self.save_path + str(repeat) + '/'
        if not os.path.isdir(self.path):
            os.mkdir(self.path)
        torch.save(self.state_dict(), self.path+'model_checkpoint')
        pd.to_pickle(loss_per_epoch, self.path+'loss_per_epoch.pkl')
    
    def load_model(self, path):
        weights = torch.load(path, map_location=self.device)
        self.load_state_dict(weights)        
</code></pre>
<p>utils.py code</p>
<pre><code class="lang-auto">import torch
import torch.nn as nn
import numpy as np
import pandas as pd
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.metrics import recall_score, precision_score, accuracy_score

def index_data():    
    drugPair2effect = pd.read_pickle('../data/drugPair2effect_idx.pkl')
    y_all = list(drugPair2effect.values())
    
    mlb = MultiLabelBinarizer()
    mlb.fit_transform(y_all)
    
    labels = sorted(list(set(y_all)))
    
    label2idx = {}
    for i, j in enumerate(labels):
        label2idx[j] = i
        
    drugPair2effectIdx = {}
    for k, v in drugPair2effect.items():
        drugPair2effectIdx[k] = label2idx[v]
        
    idx2label = np.zeros(len(label2idx), dtype='O')
    for k, v in label2idx.items():
        idx2label[v] = np.array(k)
    
    return mlb, label2idx, idx2label, drugPair2effectIdx


def convert_tensor(x_idx, y_idx, SS_mat, TS_mat, GS_mat, mlb, idx2label):    
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    
    SS = torch.tensor(SS_mat[x_idx].reshape(len(x_idx), len(SS_mat)*2)).float()
    TS = torch.tensor(TS_mat[x_idx].reshape(len(x_idx), len(TS_mat)*2)).float()
    GS = torch.tensor(GS_mat[x_idx].reshape(len(x_idx), len(GS_mat)*2)).float()
    y = torch.tensor(mlb.transform(idx2label[y_idx])).float()
    
    return SS, TS, GS, y

def evaluate_model(answer, prediction):
    accuracy = accuracy_score(answer, prediction)
    macro_recall = recall_score(answer, prediction, average='macro')
    macro_precision = precision_score(answer, prediction, average='macro')
    micro_recall = recall_score(answer, prediction, average='micro')
    micro_precision = precision_score(answer, prediction, average='micro')
    
    return accuracy, macro_recall, macro_precision, micro_recall, micro_precision

</code></pre>
<p>i need help please</p>

KFrank: <p>Hi Mahmoud!</p>
<aside class="quote no-group" data-username="mahmoud_ramadan_muha" data-post="1" data-topic="179879" data-full="true">
<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/mahmoud_ramadan_muha/48/60492_2.png" class="avatar"> mahmoud_ramadan_muha:</div>
<blockquote>
<p>RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation:</p>
</blockquote>
</aside>
<p>For some suggestions about how to debug such inplace-modification errors,<br>
see this post:</p>
<aside class="quote quote-modified" data-post="7" data-topic="171826">
  <div class="title">
    <div class="quote-controls"></div>
    <img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/k/ecb155/48.png" class="avatar">
    <a href="https://discuss.pytorch.org/t/runtimeerror-one-of-the-variables-needed-for-gradient-computation-has-been-modified-by-an-inplace-operation-torch-floattensor-64-1-which-is-output-0-of-asstridedbackward0-is-at-version-3-expected-version-2-instead-hint-the-backtrace-further-a/171826/7">"RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [64, 1]], which is output 0 of AsStridedBackward0, is at version 3; expected version 2 instead. Hint: the backtrace further a</a> <a class="badge-category__wrapper " href="/c/autograd/7"><span data-category-id="7" data-drop-close="true" class="badge-category " title="A category of posts relating to the autograd engine itself."><span class="badge-category__name">autograd</span></span></a>
  </div>
  <blockquote>
    Hi Fahmyadan and Sangyoon! 

Here are some suggestions about how to track down (and maybe fix) 
inplace-modification errors.  Note that an inplace modification in the forward 
pass is not necessarily* an error – it depends on whether and how the tensor 
that was modified is used in the backward pass.  Note that inplace operations 
can be useful for saving memory – if you replace an innocent inplace operation 
with an out-of-place equivalent, your training will use more memory (and, to a 
minor e…
  </blockquote>
</aside>

<aside class="quote no-group">
<blockquote>
<pre><code class="lang-auto">                self.AE_opt1.zero_grad()
                AE_loss1 = self.AE_criterion(o1, x1) 
                AE_loss1.backward(retain_graph=True)
                self.AE_opt1.step()
                
                self.AE_opt2.zero_grad()
                AE_loss2 = self.AE_criterion(o2, x2)
                AE_loss2.backward(retain_graph=True)
                self.AE_opt2.step()
                
                self.AE_opt3.zero_grad()
                AE_loss3 = self.AE_criterion(o3, x3)
                AE_loss3.backward(retain_graph=True)
                self.AE_opt3.step()
</code></pre>
</blockquote>
</aside>
<p>As discussed in the linked post, these <code>backward (retain_graph=True)</code> calls<br>
often cause inplace-modification errors, so you should make a particular point<br>
of looking at them while debugging your issue.</p>
<p>Best.</p>
<p>K. Frank</p>