My model seems not to be training

username: Patrice
cooked: <p>Hello dear engineers,<br>
Hope you are all doing well. I am still in my first steps in both pytorch and programming. My task is a binary segmentation problem which I would like to approach it as a binary classification. My data are RGB of size (360, 360, 3) and the labels are black and white. I have adopted the following simple CNN model for the training process.</p>
<pre><code class="lang-auto">class CNNModel(nn.Module):
    def __init__(self):
        super(CNNModel, self).__init__()

        self.cnn1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=5, stride=1, padding=0)
        self.relu1 = nn.ReLU()
        self.maxpool1 = nn.MaxPool2d(kernel_size=2)

        self.cnn2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=5, stride=1, padding=0)
        self.relu2 = nn.ReLU()
        self.maxpool2 = nn.MaxPool2d(kernel_size=2)

        self.dropout = nn.Dropout(p=0.5)

        #self.fc1 = nn.Linear(32 * 4* 4, 2)
        self.fc1 = nn.Linear(32 * 87 * 87, 2)

    def forward(self, x):
        out = self.cnn1(x)
        out = self.relu1(out)
        out = self.maxpool1(out)
        out = self.cnn2(out)
        out = self.relu2(out)
        out = self.maxpool2(out)
        out = out.view(out.size(0), -1)
        out = self.dropout(out)
        out = self.fc1(out)

        return out
</code></pre>
<p>My training function is as follows.</p>
<pre><code class="lang-auto">
opt = Config()
device = torch.device('cuda') if opt.use_gpu else torch.device('cpu')
num_classes = 2

train_dataset = Dataset(opt.train_input, opt.train_label)
print(len(train_dataset))
# print(train_dataset.__getitem__(0)[0].shape)
train_loader = data.DataLoader(train_dataset,
                                batch_size=opt.train_batch_size,
                                shuffle=True,
                                num_workers=opt.num_workers)

valid_dataset = Dataset(opt.valid_input, opt.valid_label)

print(len(valid_dataset))
valid_loader = data.DataLoader(valid_dataset,
                                batch_size=opt.train_batch_size,
                                shuffle=True,
                                num_workers=opt.num_workers)


CE = nn.CrossEntropyLoss().to(device)


def train(train_loader, model, optimizer, criterion=CE):

    model.train()

    for i, (input, target) in enumerate(tqdm(train_loader)):
        # if idx.size(0) != opt.train_batch_size:
        #     break

        input = torch.autograd.Variable(input.to(device))
        target = torch.autograd.Variable(target.to(device))
        # input = input.to(device)
        # target = target.to(device)
        target = target.long()
        output = model(input)
        #print(target.shape, output.shape)
        #print(torch.max(target, 1))
        loss = criterion(output, target[:,2,0,0])

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()


def test(model, test_loader):
    model.eval()
    correct = 0
    total = 0

    for i, (input, target) in enumerate(tqdm(test_loader)):
        input = torch.Tensor(input).to(device)
        target = torch.autograd.Variable(target).to(device)

        total += target.size(0)
        output = model(input)
        print(target.shape, output.shape)
        _, predicted = output.max(1)
        correct += predicted.eq(target[:,2,0,0]).sum().item()

    accuracy = 100. * correct / total

    return accuracy


def main_ce():
    model_ce = CNNModel().to(device)
    best_valid_acc = 0

    for epoch in range(20):
        print("epoch=", epoch)
        #print("r=", r)
        learning_rate = 1e-4
        optimizer_ce = torch.optim.Adam(model_ce.parameters(), lr=learning_rate)
        print("traning model_ce...")
        train(train_loader=train_loader, model=model_ce, optimizer=optimizer_ce)
        print("validating model_ce...")
        valid_acc = test(model=model_ce, test_loader=valid_loader)
        print('valid_acc=', valid_acc)
        if valid_acc &gt;= best_valid_acc:
            best_valid_acc = valid_acc
            torch.save(model_ce, './model_ce_' + str(1) + '_' + str(1) + '_' + str(1))
            print("saved.")
        print("testing model_ce...")
        test_acc = test(model=model_ce, test_loader=valid_loader)
        print('test_acc=', test_acc)



if __name__ == '__main__':
    main_ce()
</code></pre>
<p>The code can run without bugs. However, the accuracy remains unchanged after training for 20 epochs. I feel like there is something wrong with the codes. Please, could anyone help me check it out? Any comments or suggestions would be highly appreciated.</p>

username: ptrblck
cooked: <p>I would recommend to try to overfit a small data sample (e.g. just 10 samples) and make sure your model is able to do so.<br>
If that doesn’t work out of the box, you could play around with some hyperparameters.<br>
Once this is done, you could (carefully) scale up the problem again.</p>

username: Patrice
cooked: <p>Dear Mr. Ptrblck,<br>
Thank you very much for the suggestion. I am sorry for the late reply. I have been trying other alternatives    read from this forum. In fact, my data are RGB images from which I generated the corresponding labels. After checking carefully, I noticed that the labels are also having three channels. Then I have tried to fix them as follows.</p>
<pre><code class="lang-auto">label = np.where(label_img &gt; 0.0, 1, 0)
</code></pre>
<p>When I print the labels out, the shape is (N,H,W). Please, am I right doing it this way? How can I map the colors to obtain grayscale labels?</p>

username: ptrblck
cooked: <p>Since you are using two output channels in your model and <code>nn.CrossEntropyLoss</code>, you would have to apply a mapping between the colors of your target maps and the class indices.<br>
If your current targets contain (normalized) RGB values, <code>label</code> would be a tensor full of ones.</p>

username: Patrice
cooked: <p>Thank you for your suggestions. Unfortunately, I am facing some hardware problems presently. I will give it a try and give you feedback after fixing my computer.</p>