CNN produces the same output for different inputs

username: Nyx
cooked: <p>Hi,<br>
I’m trying to train a CNN model using a TripletMarginLoss. However, the model gives the same output for both the anchors, positives and negatives images, why is that?</p>
<p>the following is the model code and a training loop using random tensors:</p>
<pre><code class="lang-auto">import torch.utils
import torch.utils.data
import cfg
import torch
from torch import nn




class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.layers = []
        self.layers.append(nn.LazyConv2d(out_channels=8, kernel_size=1, stride=1))
        for i in range(cfg.BLOCKS_NUMBER):
            if i == 0: 
                self.layers.append(nn.LazyConv2d(out_channels=16, kernel_size=5, padding=2, stride=1))
                self.layers.append(nn.Sigmoid())
                self.layers.append(nn.LazyConv2d(out_channels=16, kernel_size=5, padding=2, stride=1))
                self.layers.append(nn.Sigmoid())
                self.layers.append(nn.LazyConv2d(out_channels=16, kernel_size=5, padding=2, stride=1))
                self.layers.append(nn.Sigmoid())
            else: 
                self.layers.append(nn.LazyConv2d(out_channels=256, kernel_size=3, padding=1, stride=1))
                self.layers.append(nn.Sigmoid())
                self.layers.append(nn.LazyConv2d(out_channels=256, kernel_size=3, padding=1, stride=1))
                self.layers.append(nn.Sigmoid())
                self.layers.append(nn.LazyConv2d(out_channels=256, kernel_size=3, padding=1, stride=1))
                self.layers.append(nn.Sigmoid())
            
            self.layers.append(nn.MaxPool2d(kernel_size=2, stride=2, padding=1))
        
        self.layers.append(nn.Flatten())
        self.model = nn.Sequential(*self.layers)
        


    def forward(self, anchors, positives, negatives):

        a = self.model(anchors)
        p = self.model(positives)
        n = self.model(negatives)

        return a, p, n





model = Model()

model.to(cfg.DEVICE)

criterion = nn.TripletMarginLoss(margin=1.0, swap=True)
optimizer = torch.optim.Adam(model.parameters(), lr=0.1)

anchors = torch.rand((10, 1, 560, 640))
positives = torch.rand((10, 1, 560, 640))
negatives = torch.rand((10, 1, 560, 640))

anchor_set = torch.utils.data.TensorDataset(anchors)
anchor_loader = torch.utils.data.DataLoader(anchors, batch_size=10, shuffle=True)

positive_set = torch.utils.data.TensorDataset(positives)
positive_loader = torch.utils.data.DataLoader(positives, batch_size=10, shuffle=True)

negative_set = torch.utils.data.TensorDataset(negatives)
negative_loader = torch.utils.data.DataLoader(negatives, batch_size=10, shuffle=True)


model.train()
for epoch in range(20):
    print(f"start epoch-{epoch} : ")

    for anchors in anchor_loader:
        for positives in positive_loader:
            for negatives in negative_loader:
            
                anchors = anchors.to(cfg.DEVICE)
                positives = positives.to(cfg.DEVICE)
                negatives = negatives.to(cfg.DEVICE)

                anchors_encodings, positives_encodings, negatives_encodings = model(anchors, positives, negatives)


                loss = criterion(anchors_encodings, positives_encodings, negatives_encodings)
                optimizer.zero_grad()   
                loss.backward(retain_graph=True)
                torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)

                print("a = ", anchors_encodings[0, :50])
                print("p = ", positives_encodings[0, :50])
                print("n = ", negatives_encodings[0, :50])

                print("loss = ", loss)
            
                optimizer.step()

</code></pre>

username: Bjorn_Lindqvist
cooked: <p>Difficult to say without seeing the full code. What are the values of the fields in <code>cfg</code>? Perhaps the sigmoids are squeezing the range of the values or perhaps the number of blocks is too large. Note that since you are using random numbers for the categories, the model output should be “approximately equal” for every category.</p>