Why my accuracy values don´t change on my train model

username: Alicia_Ojeda
cooked: <p>Hi, I am using transfer learning to classify histological breast cancer images with VGG16 pre-trained. I have 7900 images y I separated in train, val and test. I have made a custom dataset to read the images and edit the train model function from <a href="https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html" rel="nofollow noopener">https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html</a></p>
<p>My accuracy in train and val doesn´t change and I don´t know why, can you please chek it out, than you. Also, my loss it´s so high!</p>
<p>I´m pretty new in this</p>
<p>The code I use is here:</p>
<pre><code class="lang-auto">class BreakHistDataset(Dataset):
   
        def __init__(self, csv_file, root_dir,transform=None):
            self.df = pd.read_csv(csv_file)
            self.root_dir = root_dir
            self.transform = transform
    
        def __len__(self):
           return len(self.df)
    
        def __getitem__(self, idx):
    
            img_name = os.path.join(self.root_dir,self.df.iloc[idx, 3])
            image = io.imread(img_name)
            labels = self.df.iloc[idx, 4]
            
            
    
            if self.transform:
                image = self.transform(image)

            
            return image,labels

</code></pre>
<pre><code>transforme_train = transforms.Compose([
     transforms.ToPILImage(),
     transforms.Resize(256),
     transforms.CenterCrop(224),
     transforms.RandomHorizontalFlip(),
     transforms.RandomVerticalFlip(),
     transforms.ToTensor(),
     transforms.Normalize([0.7890, 0.6167, 0.7618],[0.1047, 0.1388, 0.0894])])

transforme_val = transforms.Compose([
   transforms.ToPILImage(),
   transforms.Resize(256),
   transforms.CenterCrop(224),
   transforms.ToTensor(),
   transforms.Normalize([0.7890, 0.6167, 0.7618],[0.1047, 0.1388, 0.0894])])

transforme_test = transforms.Compose([
   transforms.ToPILImage(),
   transforms.Resize(256),
   transforms.CenterCrop(224),
   transforms.ToTensor(),
   transforms.Normalize([0.7890, 0.6167, 0.7618],[0.1047, 0.1388, 0.0894])])
</code></pre>
<pre><code class="lang-auto">
</code></pre>
<pre><code>bh_dataset_train = BreakHistDataset(csv_file='/content/gdrive2/My Drive/breakhis/train1.csv',root_dir='/content/gdrive2/My Drive/breakhis/BreaKHis_v1', transform = transforme_train)
bh_dataset_val = BreakHistDataset(csv_file='/content/gdrive2/My Drive/breakhis/val.csv',root_dir='/content/gdrive2/My Drive/breakhis/BreaKHis_v1', transform = transforme_val)
bh_dataset_test = BreakHistDataset(csv_file='/content/gdrive2/My Drive/breakhis/test.csv',root_dir='/content/gdrive2/My Drive/breakhis/BreaKHis_v1', transform = transforme_test)
</code></pre>
<pre><code class="lang-auto">
</code></pre>
<pre><code>train_loader = DataLoader(bh_dataset_train, batch_size=32,shuffle=True)
val_loader = DataLoader(bh_dataset_val, batch_size=32,shuffle=True)
test_loader = DataLoader(bh_dataset_test, batch_size=32,shuffle=True)
</code></pre>
<pre><code class="lang-auto">
</code></pre>
<pre><code>use_gpu = torch.cuda.is_available()

def train_model(model, criterion, optimizer, scheduler, num_epochs=10):
      since = time.time()
      best_model_wts = model.state_dict()
      best_acc = 0.0
      p_epoch = tqdm(range(num_epochs))

      for epoch in p_epoch:
        print('Epoch {}/{}'.format(epoch, num_epochs - 1))
        print('-' * 10)

        loss_train = 0.0
        corrects_train = 0
        loss_val = 0.0
        corrects_val = 0

         w = []
         l = []

        for img, labels in tqdm(train_loader):
           if use_gpu:
              img = img.cuda()
              labels = labels.cuda()
           else:
               img, labels = img, labels
    
           model.train(True) 
           optimizer.zero_grad()
    
           outputs = model(img)
           _, preds = torch.max(outputs.data, 1)
           loss = criterion(outputs, labels)
    
           loss.backward()
           optimizer.step()
           scheduler.step()

           loss_train += loss 
           l.append(loss_train)
           corrects_train += (preds == labels.data).sum().item()
            
      epoch_loss = loss_train / len(train_loader)
      epoch_acc = corrects_train / len(train_loader)
      w.append(epoch_acc)

      plt.title('Loss vs Epocas')
      plt.xlabel('Epocas')
      plt.ylabel('Loss')
      plt.plot(l,label = 'loss train')
      plt.plot(figsize=(20, 10))
      plt.legend()

       print('{} Loss: {:.4f} Acc: {:.4f} RunCorr: {:.4f}'.format('train', epoch_loss, 
       epoch_acc,corrects_train))      
        
   
       r = []
       m = []   

     for img, labels in tqdm(val_loader):

         if use_gpu:
            img = img.cuda()
            labels = labels.cuda()
         else:
            img, labels = img, labels

        model.train(False) 
        
        optimizer.zero_grad()

        outputs = model(img)
        _, preds = torch.max(outputs.data, 1)
        loss = criterion(outputs, labels)
        
       loss_val += loss
       r.append(loss_val)
       corrects_val += (preds == labels.data).sum().item()
          
     
   epoch_loss_val = loss_val / len(val_loader)
   epoch_acc_val = corrects_val / len(val_loader)
   m.append( epoch_acc_val)

   print('{} Loss: {:.4f} Acc: {:.4f}'.format('val', epoch_loss_val, epoch_acc_val))
    

   if epoch_acc_val &gt; best_acc:
     best_acc = epoch_acc_val
     best_model_wts = model.state_dict()
            
time_elapsed = time.time() - since
print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))
print('Best val Acc: {:4f}'.format(best_acc))

 # load best model weights
model.load_state_dict(best_model_wts)
return model
</code></pre>
<pre><code class="lang-auto">
</code></pre>
<pre><code>num_classes = 8
model_conv = torchvision.models.vgg16(pretrained=True)
for param in model_conv.parameters():
param.requires_grad = False

num_features = model_conv.classifier[6].in_features
features = list(model_conv.classifier.children())[:-1] # Remove last layer
features.extend([nn.Linear(num_features, num_classes)])# Add our layer with 4 outputs
model_conv.classifier = nn.Sequential(*features) # Replace the model classifier
print(model_conv)
</code></pre>
<pre><code class="lang-auto">
</code></pre>
<pre><code>if use_gpu:
  model_conv = model_conv.cuda()

criterion = nn.CrossEntropyLoss()
optimizer_conv = optim.Adam(model_conv.classifier.parameters(), lr=0.0001,betas = [0.9, 
0.999])
exp_lr_scheduler = lr_scheduler.StepLR(optimizer_conv, step_size=7, gamma=0.1)
model_conv = train_model(model_conv ,criterion, optimizer_conv,exp_lr_scheduler )
</code></pre>
<pre><code class="lang-auto">
Results for all the epochs

train Loss: 1.6865 Acc: 14.3810 
val Loss: 1.6122 Acc: 15.5312</code></pre>

username: ptrblck
cooked: <p>The code looks generally alright.<br>
There is one issue, which might create a growing memory usage and could thus trigger an out of memory error.<br>
In these lines of code it seems you are directly storing the <code>loss</code>, which is still attached to the computation graph:</p>
<pre><code class="lang-python">loss_train += loss 
l.append(loss_train)
</code></pre>
<p>Store the detached tensor, if the loss list is just used to calculate the average loss etc.:</p>
<pre><code class="lang-python">loss_train += loss.item()
</code></pre>
<p>Have you tried to unfreeze the model and train it completely?<br>
If so, what was the highest accuracy you could achieve?<br>
Note that the pretrained models were trained on ImageNet12. The input images were thus normalized with:</p>
<pre><code class="lang-python">normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                 std=[0.229, 0.224, 0.225])
</code></pre>
<p>While it seems you’ve calculated the image statistics manually based on your dataset or where do these values come from?</p>

username: Alicia_Ojeda
cooked: <p>Thanks for the answer!! I’m gonna check the loss.<br>
Q1: I haven’t tried to train it completely, but i will try it.<br>
Q2: The highest accuracy achived is 60%.</p>
<p>Q3: Yes I’ve calculated the statistics manually based on the dataset with this code:</p>
<pre><code class="lang-auto">mean = 0.
std = 0.
for images in train_loader:
    batch_samples = images.size(0) 
    images = images.view(batch_samples, images.size(1), -1)
    mean += images.mean(2).sum(0)
    std += images.std(2).sum(0)

mean /= len(train_loader.dataset)
std /= len(train_loader.dataset)
</code></pre>

username: Alicia_Ojeda
cooked: <p>Hi again, I change in my train function this: loss_train += loss.item(), also I noticed that the classes of the dataset were unbalanced so I used this code to balance them. Even doing that my accuracy doesn´t change. What can I do?  Here is the code for the balance:</p>
<pre><code class="lang-auto">class_weights_train = 1./torch.Tensor(class_sample_counts_train)
class_weights_train = class_weights_train.double()

train_targets = [sample[1] for sample in bh_dataset_train]
train_samples_weight = [class_weights_train[class_id] for class_id in train_targets]

class_sample_counts_val = [48,1138,331,324,245,189,235,251]

class_weights_val = 1./torch.Tensor(class_sample_counts_val)
class_weights_val = class_weights_val.double()

val_targets = [sample[1] for sample in bh_dataset_val]
val_samples_weight = [class_weights_val[class_id] for class_id in val_targets]

train_sampler = torch.utils.data.sampler.WeightedRandomSampler(train_samples_weight, len(bh_dataset_train))
val_sampler = torch.utils.data.sampler.WeightedRandomSampler(val_samples_weight, len(bh_dataset_val))
</code></pre>

username: ptrblck
cooked: <p>You could scale down the problem and try to (perfectly) overfit a small data snippet, e.g. just 10 samples from your dataset.<br>
If your model is not able to overfit these samples, you might need to further fine tune the hyperparameters.<br>
Let me know, if this still doesn’t work, as there might then be subtle code bugs, which I’m missing at the moment.</p>