Code transfer from Keras to PyTorch (Unet/MSELoss())

username: Mukesh1729
cooked: <p>When I changed my code from Keras to PyTorch, I am not able to reproduce the results that I was getting in Keras in PyTorch.</p>
<p>I am using the MSELoss() as my loss function with an Unet architecture. Basically, my model learns well but my inference turns out to be bad.</p>
<p>What could be resulting in such a problem?<br>
I have checked my code but I am not able to reproduce the same result while keeping all the parameters the same.</p>
<p>Thanks</p>

username: ptrblck
cooked: <aside class="quote no-group" data-username="Mukesh1729" data-post="1" data-topic="131245">
<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/m/90db22/48.png" class="avatar"> Mukesh1729:</div>
<blockquote>
<p>I am using the MSELoss() as my loss function with an Unet architecture. Basically, my model learns well but my inference turns out to be bad.</p>
</blockquote>
</aside>
<p>Are you training both models (Keras and PyTorch) from scratch and do both converge to approx. the same training loss? Afterwards, when trying to evaluate the model using the validation dataset you are seeing a worse validation loss in PyTorch only? If so, did you call <code>model.eval()</code> and made sure to use the same preprocessing on the validation samples in both approaches?</p>
<aside class="quote no-group" data-username="Mukesh1729" data-post="1" data-topic="131245">
<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/m/90db22/48.png" class="avatar"> Mukesh1729:</div>
<blockquote>
<p>I have checked my code but I am not able to reproduce the same result while keeping all the parameters the same.</p>
</blockquote>
</aside>
<p>Does this mean that you are loading the trained parameters from Keras into the PyTorch model, but the output is still different?</p>

username: Mukesh1729
cooked: <p>Thanks for getting back.</p>
<ul>
<li>I am training the model in Keras and PyTorch and they converge approx. (architecture below)</li>
<li>I  am using the model.eval() with similar preprocessing steps. Do you think think the validation loss is bad from the output below?</li>
<li>I am training the model in ex: PyTorch and saving it and loading it in PyTorch.</li>
<li>Similarly, train in Keras, save, load in Keras, and test</li>
</ul>
<p><strong>Code reference</strong></p>
<h1>
<a name="load-data-1" class="anchor" href="#load-data-1"></a>Load data</h1>
<pre><code class="lang-auto">class DBData(torch.utils.data.Dataset):

    """DATALOADER TRAINING, VALIDATION SETS"""

    def __init__(self, 

                 fringe_images,

                 hwrap_images,

                 transform=None):

      """

        Args:

            fringe_dir: Directory with all the images.

            hwrap_dir: Directory with all the targets.

            transform (callable, optional): Optional transform to be applied

                on a sample.

        """

      self.fringe_dir = fringe_images

      self.hwrap_dir  = hwrap_images

      self.transform  = None

      self.count = len(self.fringe_dir)

    def __len__(self):

        return len(self.fringe_dir)

    def make_grayscale(self,img):

        # Transform color image to grayscale

        gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        return gray_img

    def __getitem__(self, ix):

        #image

        image = cv2.imread(self.fringe_dir[ix])

        image = self.make_grayscale(image)

        image = image/255.0 

        image = np.expand_dims(image, axis=-1)

        image = torch.from_numpy(image).permute(2, 0, 1).float()

        #mask

        target  = cv2.imread(self.hwrap_dir[ix])

        target  = self.make_grayscale(target)

        target  = target/255.0

        target = np.expand_dims(target, axis=-1)

        target = torch.from_numpy(target).permute(2, 0, 1).float()

        return {

            'image':image,

            'target': target 

            }
</code></pre>
<h1>
<a name="model-blocks-2" class="anchor" href="#model-blocks-2"></a>model blocks</h1>
<pre><code class="lang-auto">
def up_block(in_channels, out_channels):

    """DECODING BLOCK"""

    conv_block = torch.nn.Sequential(

                                    torch.nn.Conv2d(in_channels, 

                                                    out_channels,

                                                    padding="same",

                                                    kernel_size=3),

                                    #torch.nn.BatchNorm2d(out_channels),

                                    torch.nn.ReLU(inplace=True),

                                )

    return conv_block

def down_block(in_channels, out_channels):

    """ENCODING  BLOCK"""

    conv_block = torch.nn.Sequential(

                                    torch.nn.Conv2d(in_channels, 

                                                    out_channels, 

                                                    kernel_size=3, 

                                                    padding="same"),

                                    #torch.nn.BatchNorm2d(out_channels),

                                    torch.nn.ReLU(inplace=True),

                                    torch.nn.Conv2d(out_channels, 

                                                    out_channels,

                                                    kernel_size=3, 

                                                    padding="same"),

                                    #torch.nn.BatchNorm2d(out_channels),

                                    torch.nn.ReLU(inplace=True),

                                )

    return conv_block

def out(in_channels, out_channels):

    """CLASSIFICATION-FINAL CONVOLUTIONAL LAYER"""

    conv_layer = torch.nn.Sequential(

                 torch.nn.Conv2d(in_channels,

                                 out_channels,

                                 kernel_size=1),

                 torch.nn.ReLU(inplace=True)

    )

    return conv_layer

  

def out_reg(in_channels, out_channels):

    """REGRESSION-FINAL CONVOLUTIONAL LAYER"""

    conv_layer = torch.nn.Sequential(

                 torch.nn.Conv2d(in_channels, 

                                 out_channels, 

                                 kernel_size=3,

                                 padding="same")

    )

    return conv_layer
</code></pre>
<pre><code class="lang-auto">
# model setup

class UNet1(torch.nn.Module):

    """UNET ARCHITECTURE REGRESSION"""

    def __init__(self):

        super(UNet1, self).__init__()

        self.pool = torch.nn.MaxPool2d((2, 2))

        self.up_samp = torch.nn.Upsample(

                                        scale_factor=2, 

                                        mode="nearest"

                                        )

        self.down_conv1 = down_block(1, 32)

        self.down_conv2 = down_block(32, 64)

        self.down_conv3 = down_block(64, 128)

        self.down_conv4 = down_block(128, 256)

        self.down_conv5 = down_block(256, 512)

        self.down_conv6 = down_block(512, 1024)

        self.up_conv1 = up_block(1024, 512)

        self.up_conv2 = up_block(512, 256)

        self.up_conv3 = up_block(256, 128)

        self.up_conv4 = up_block(128, 64)

        self.up_conv5 = up_block(64, 32)

        self.out_reg = out_reg(32, 1)

    def forward(self, image):

        # Encoding section

        e1 = self.down_conv1(image)

        p1 = self.pool(e1)

        e2 = self.down_conv2(p1)

        p2 = self.pool(e2)

        e3 = self.down_conv3(p2)

        p3 = self.pool(e3)

        e4 = self.down_conv4(p3)

        p4 = self.pool(e4)

        e5 = self.down_conv5(p4)

        p5 = self.pool(e5)

        e6 = self.down_conv6(p5)

        # Decoding section

        u1 = self.up_samp(e6)

        d1 = self.up_conv1(u1)

        c1 = self.up_conv1(torch.cat([e5, d1], axis=1))

        u2 = self.up_samp(c1)

        d2 = self.up_conv2(u2)

        c2 = self.up_conv2(torch.cat([e4, d2], axis=1))

        u3 = self.up_samp(c2)

        d3 = self.up_conv3(u3)

        c3 = self.up_conv3(torch.cat([e3, d3], axis=1))

        u4 = self.up_samp(c3)

        d4 = self.up_conv4(u4)

        c4 = self.up_conv4(torch.cat([e2, d4], axis=1))

        u5 = self.up_samp(c4)

        d5 = self.up_conv5(u5)

        c5 = self.up_conv5(torch.cat([e1, d5], axis=1))

        # print('Encoding dims','\ne1:', e1.shape, '\ne2:',e2.shape, '\ne3:',e3.shape, '\ne4:',e4.shape,'\ne5:',e5.shape,'\ne6:',e6.shape)

        # print('\n')

        # print('Decoding dims','\nd1:', d1.shape, '\nd2:', d2.shape, '\nd3:', d3.shape, '\nd4:', d4.shape, '\nd5:', d5.shape,'/nout')

        return self.out_reg(c5)

#Check what our model returns as output

model=UNet1()
model(torch.randn(1, 1, 160, 160)).shape
</code></pre>
<pre><code class="lang-auto">
#train, validation
def train(dataset, 

          data_loader, 

          model, 

          criterion, 

          optimizer, 

          DEVICE,

          task_type, 

          save=False

          ):

    """TRAINING"""

    model.train()

    running_loss = 0.0

    tr = []

    num_batches = int(len(dataset) / data_loader.batch_size)

    tk0 = tqdm(data_loader, total=num_batches)

    for d in tk0:

      inputs  = d["image"]

      targets = d["target"]

      #checkpoint

      # print(inputs.squeeze(0).numpy().squeeze(0).shape)

      # plt.imshow(inputs.squeeze(0).numpy().squeeze(0), cmap='gray')

      # # plt.imshow(targets.squeeze(0).numpy().squeeze(0), cmap='gray')

      inputs  = inputs.to(DEVICE, dtype=torch.float)

      targets = targets.to(DEVICE)

      optimizer.zero_grad()

      outputs       = model(inputs)

      loss          = criterion(outputs, targets)

      running_loss += loss

      #Classification

      #acc = (torch.max(outputs, 1)[1] == targets).float().mean()

      

      loss.backward()

      optimizer.step()

    tk0.close()

    return running_loss/num_batches#, acc

def evaluate(dataset,

             data_loader,

             model,

             criterion,

             scheduler, 

             DEVICE,

             task_type, 

             ):

    

    """EVALUTION STEP"""

    model.eval()

    final_loss = 0.0

    num_batches = int(len(dataset) / data_loader.batch_size)

    tk0 = tqdm(data_loader, total=num_batches)

    val = []

    with torch.no_grad():

        for d in tk0:

          inputs  = d["image"]

          targets = d["target"]

          inputs  = inputs.to(DEVICE, dtype=torch.float)

          targets = targets.to(DEVICE)

          

          #computation

          outputs = model(inputs)

          loss = criterion(outputs, targets)

          #Classification

          #acc = (torch.max(outputs, 1)[1] == targets).float().mean()

          final_loss += loss

          #scheduler.step(loss)

    # close tqdm

    tk0.close()

    return final_loss/num_batches #, acc
</code></pre>
<pre><code class="lang-auto">#train loop
def train_loop(model, 

               optimizer, 

               criterion, 

               EPOCHS,

               fringe_images_train,

               hwrap_images_train,

               fringe_images_test,

               hwrap_images_test

               ):

    """RUNS TRAINING AND VALIDATION"""

    #Training parameters

    EPOCHS = EPOCHS

    best_accuracy = 0.0

    early_stopping_counter = 0.0

    # Define optimizer and criterion = loss function

    optimizer = optimizer

    criterion = criterion

    #Load model

    DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'

    model = model

    model.to(DEVICE)

    #Dataloaders (Training and validation)

    train_dataset = DBData(fringe_images_train, hwrap_images_train)

    valid_dataset = DBData(fringe_images_test, hwrap_images_test)

    train_loader = torch.utils.data.DataLoader(

                                            train_dataset,

                                            batch_size=1,

                                            shuffle=False,

                                            num_workers=0

                                            )

    valid_loader = torch.utils.data.DataLoader(

                                            valid_dataset,

                                            batch_size=1,

                                            shuffle=False,

                                            num_workers=0

                                            )

    #LR scheduler

    scheduler = lr_scheduler.ReduceLROnPlateau(

                                              optimizer, 

                                              mode="min", 

                                              patience=3, 

                                              verbose=True

                                              )

    

    print("Starting to train model using the following parameters")

    print(f"Training on {DEVICE}")

    

    # Training loop

    for epoch in range(EPOCHS):

        #print(f"Training Epoch: {epoch}",optimizer.param_groups[0]['lr'])

        train_log = train(

                          dataset=train_dataset,

                          data_loader=train_loader,

                          model=model,

                          criterion=criterion,

                          optimizer=optimizer,

                          DEVICE = DEVICE,

                          task_type=None #regression or classification

                          )

        # calculate validation loss

        val_log = evaluate(

                          valid_dataset,

                          valid_loader,

                          model,

                          criterion,

                          scheduler,

                          DEVICE = DEVICE,

                          task_type=None

                          )

        trn_loss = train_log

        val_loss = val_log

        #Early stopping (early_stopping_counter=&gt;patience)

        # if val_acc&gt; best_accuracy:

        #       best_accuracy = val_acc

        # else:

        #       early_stopping_counter += 1

        # if early_stopping_counter &gt; 2:

        #       raise Exception("Early stopping")

        print(f"Training/Validation set{epoch}", 

              'train_loss:',trn_loss.detach().cpu().numpy(), 

              'val_loss:',val_loss.detach().cpu().numpy()

              )

    print('routine complete')

    return trn_loss.detach().cpu().numpy(), val_loss.detach().cpu().numpy()
</code></pre>
<p><span class="hashtag">#skipping</span> training part</p>
<pre><code class="lang-auto">
#
save model

epoch = 30

    state = {

              'epoch': epoch+1,

              'state_dict': model.state_dict(),

              'optimizer': optimizer.state_dict(),

              'learning_rate':1e-3,

          }

    torch.save(state, "DB_model.pth")
</code></pre>
<pre><code class="lang-auto">
#inference
'''
#Load saved model

model = UNet1()

learning_rate = 1e-2

criterion = torch.nn.MSELoss()

optimizer = torch.optim.SGD(model.parameters(), 

                            lr=learning_rate,

                            weight_decay = 1e-4,  

                            momentum=0.9,

                            nesterov=True)

#Load stored values

checkpoint = torch.load("DB_model.pth")

model = model.load_state_dict(checkpoint['state_dict'])

optimizer = optimizer.load_state_dict(checkpoint['optimizer'])

#print(checkpoint['optimizer'])

EPOCHS = checkpoint['epoch']

#load image and mask

def make_grayscale(img):

    # Transform color image to grayscale

    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    return gray_img

image = cv2.imread("/content/i/img6.png")

image = make_grayscale(image)

image = image/255.0 

image = np.expand_dims(image, axis=-1)

images = torch.from_numpy(image).unsqueeze(0).permute(0,3,1,2).float()

mask  = cv2.imread("/content/w/img6.png",0)

with torch.no_grad():

  

    #load saved model

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    model = UNet1()

    checkpoint=torch.load('DB_model.pth')

    model.load_state_dict(checkpoint['state_dict'])

    model.eval()

    #Predictions

    _mask = model(images)

    fig = plt.figure(figsize=(20, 12))

          

    # setting values to rows and column variables

    rows = 1

    columns = 3

      

    # Adds a subplot at the 1st position

    fig.add_subplot(rows, columns, 1)

      

    # showing image

    plt.imshow(images.squeeze(0).permute(1,2,0).squeeze(2).numpy(), cmap='gray')

    plt.axis('off')

    plt.title("Input")

      

    # Adds a subplot at the 2nd position

    fig.add_subplot(rows, columns, 2)

      

    plt.imshow(_mask.squeeze(0).permute(1,2,0).detach().cpu()[:,:,0]*255.0, cmap='gray')

    plt.axis('off')

    plt.title("Prediction")

      

    # Adds a subplot at the 3rd position

    fig.add_subplot(rows, columns, 3)

      

    plt.imshow(mask, cmap='gray')

    plt.axis('off')

    plt.title("target")
</code></pre>
<h1>
<a name="output-3" class="anchor" href="#output-3"></a>output</h1>
<p>Training images size (–) 116 116<br>
Validation images size (–) 27 27<br>
Regression with U-net<br>
Starting to train model using the following parameters<br>
Training on cuda</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.60it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 146.21it/s]</p>
<p>Training/Validation set0 train_loss: 0.097666755 val_loss: 0.079518124</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.73it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 146.75it/s]</p>
<p>Training/Validation set1 train_loss: 0.07775278 val_loss: 0.0782941</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.77it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 148.06it/s]</p>
<p>Training/Validation set2 train_loss: 0.0763465 val_loss: 0.07699763</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.85it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 146.83it/s]</p>
<p>Training/Validation set3 train_loss: 0.07478243 val_loss: 0.075491294</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.75it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.53it/s]</p>
<p>Training/Validation set4 train_loss: 0.07280874 val_loss: 0.07346106</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.73it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 146.83it/s]</p>
<p>Training/Validation set5 train_loss: 0.07020978 val_loss: 0.07079809</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.72it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.35it/s]</p>
<p>Training/Validation set6 train_loss: 0.06662013 val_loss: 0.066935785</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.67it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.30it/s]</p>
<p>Training/Validation set7 train_loss: 0.06101884 val_loss: 0.06107542</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.55it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.00it/s]</p>
<p>Training/Validation set8 train_loss: 0.054175895 val_loss: 0.054572243</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.70it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 148.31it/s]</p>
<p>Training/Validation set9 train_loss: 0.04758354 val_loss: 0.049077705</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.58it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 145.89it/s]</p>
<p>Training/Validation set10 train_loss: 0.042901877 val_loss: 0.045424514</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.73it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 146.80it/s]</p>
<p>Training/Validation set11 train_loss: 0.040017847 val_loss: 0.043156996</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.75it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.32it/s]</p>
<p>Training/Validation set12 train_loss: 0.038354356 val_loss: 0.041663162</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.69it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.21it/s]</p>
<p>Training/Validation set13 train_loss: 0.037522454 val_loss: 0.04087787</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.72it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 146.60it/s]</p>
<p>Training/Validation set14 train_loss: 0.037010863 val_loss: 0.040288415</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.74it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 146.93it/s]</p>
<p>Training/Validation set15 train_loss: 0.03626076 val_loss: 0.039554063</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.75it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.31it/s]</p>
<p>Training/Validation set16 train_loss: 0.03532498 val_loss: 0.039040133</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.83it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 146.97it/s]</p>
<p>Training/Validation set17 train_loss: 0.034851596 val_loss: 0.038595054</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.72it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 146.06it/s]</p>
<p>Training/Validation set18 train_loss: 0.034334905 val_loss: 0.038168218</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.80it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.23it/s]</p>
<p>Training/Validation set19 train_loss: 0.03380642 val_loss: 0.037747495</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.78it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 146.60it/s]</p>
<p>Training/Validation set20 train_loss: 0.03329962 val_loss: 0.03736325</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.78it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 145.78it/s]</p>
<p>Training/Validation set21 train_loss: 0.03276293 val_loss: 0.0369993</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.78it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.88it/s]</p>
<p>Training/Validation set22 train_loss: 0.032343842 val_loss: 0.036700852</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.75it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.29it/s]</p>
<p>Training/Validation set23 train_loss: 0.03199774 val_loss: 0.03642374</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.71it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.27it/s]</p>
<p>Training/Validation set24 train_loss: 0.03165286 val_loss: 0.036165755</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.81it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.09it/s]</p>
<p>Training/Validation set25 train_loss: 0.031332493 val_loss: 0.03593022</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.69it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 147.52it/s]</p>
<p>Training/Validation set26 train_loss: 0.03102655 val_loss: 0.03571768</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.79it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 148.23it/s]</p>
<p>Training/Validation set27 train_loss: 0.030747896 val_loss: 0.035525315</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.68it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 146.09it/s]</p>
<p>Training/Validation set28 train_loss: 0.030485038 val_loss: 0.0353475</p>
<p>100%|██████████| 116/116 [00:02&lt;00:00, 50.74it/s]<br>
100%|██████████| 27/27 [00:00&lt;00:00, 148.92it/s]</p>
<p>Training/Validation set29 train_loss: 0.03022127 val_loss: 0.03518007<br>
routine complete</p>

username: ptrblck
cooked: <aside class="quote no-group" data-username="Mukesh1729" data-post="3" data-topic="131245">
<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/m/90db22/48.png" class="avatar"> Mukesh1729:</div>
<blockquote>
<p>Do you think think the validation loss is bad from the output below?</p>
</blockquote>
</aside>
<p>It’s hard to tell, as you are trying to compare two different frameworks, so I don’t know if the validation loss is “good” in this isolated run. Since the models converge to a similar training loss, but give a different validation loss I think that something is still not right.<br>
To check it further you could pass static inputs (e.g. <code>torch.ones</code>) to the model during validation and check, if both models would return approx. the same predictions.<br>
If so, then the model itself seems to be alright and the data loading or preprocessing might be wrong.</p>

username: Mukesh1729
cooked: <p>Hey, thanks for the feedback. I will try to test it and see. The model is learning something from the loss but  do you think the inference approach I used in the above code is the right way to go?</p>

username: ptrblck
cooked: <aside class="quote no-group" data-username="Mukesh1729" data-post="5" data-topic="131245">
<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/m/90db22/48.png" class="avatar"> Mukesh1729:</div>
<blockquote>
<p>but do you think the inference approach I used in the above code is the right way to go?</p>
</blockquote>
</aside>
<p>It looks alright by just skimming through the code. You are not using any transformations during the inference run, but it also seems that no transformations (e.g. normalization) are used during training.</p>