How can I make my CNN output_feature = 1 since I am testing for 0 or 1
class BreastCancerCNN(ImageClassificationBase):
    def __init__(self):
        super().__init__()
        self.network = nn.Sequential(
            nn.Conv2d(3, 32, kernel_size=3, padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU(),
            nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(),
            nn.MaxPool2d(2, 2), # output: 64 x 16 x 16

            nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(128),
            nn.ReLU(),
            nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(128),
            nn.ReLU(),
            nn.MaxPool2d(2, 2), # output: 128 x 8 x 8

            nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(256),
            nn.ReLU(),
            nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(256),
            nn.ReLU(),
            nn.MaxPool2d(2, 2), # output: 256 x 4 x 4
            
            nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(512),
            nn.ReLU(),
            nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(512),
            nn.ReLU(),
            nn.MaxPool2d(2, 2), # output: 512 x 2 x 2

            nn.Flatten(),
            nn.Linear(256*2*2, 512),
            nn.ReLU(),
            nn.Linear(512, 256),
            nn.ReLU(),
            nn.Linear(256, 1)
            
        )
        
    def forward(self, xb):
        return self.network(xb)

@torch.no_grad()

def get_lr(optimizer):
    for param_group in optimizer.param_groups:
        return param_group['lr']

def evaluate(model, val_loader):
    model.eval()
    outputs = [model.validation_step(batch) for batch in val_loader]
    print(outputs)
    return model.validation_epoch_end(outputs)

def fit(epochs, lr, model, train_loader, val_loader, opt_func=torch.optim.SGD):
    history = []
    
    # Set up cutom optimizer with weight decay
    optimizer = opt_func(model.parameters(), lr, weight_decay=0)
    # Set up one-cycle learning rate scheduler
    sched = torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr, epochs=epochs, 
                                                steps_per_epoch=len(train_loader))
    for epoch in range(epochs):
        train_losses = []
        lrs = []
        # Training Phase 
        model.train()
        train_losses = []
        for batch in train_loader:
            loss = model.training_step(batch)
            train_losses.append(loss)
            loss.backward()
            optimizer.step()
            optimizer.zero_grad()
            
            # Record &amp; update learning rate
            lrs.append(get_lr(optimizer))
            sched.step()
            
        # Validation phase
        result = evaluate(model, val_loader)
        result['train_loss'] = torch.stack(train_losses).mean().item()
        result['lrs'] = lrs
        model.epoch_end(epoch, result)
#         print(result)
        history.append(result)
    return history 

Get data from the history after running one epoch
history = [evaluate(model, val_dl)]
history
This is the code that results in
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
/tmp/ipykernel_33/1481765314.py in &lt;module&gt;
      1 # Get data from the histrory after running one epoch
----&gt; 2 history = [evaluate(model, val_dl)]
      3 history

/tmp/ipykernel_33/559867535.py in evaluate(model, val_loader)
      7 def evaluate(model, val_loader):
      8     model.eval()
----&gt; 9     outputs = [model.validation_step(batch) for batch in val_loader]
     10     print(outputs)
     11     return model.validation_epoch_end(outputs)

/tmp/ipykernel_33/559867535.py in &lt;listcomp&gt;(.0)
      7 def evaluate(model, val_loader):
      8     model.eval()
----&gt; 9     outputs = [model.validation_step(batch) for batch in val_loader]
     10     print(outputs)
     11     return model.validation_epoch_end(outputs)

/tmp/ipykernel_33/1785597948.py in validation_step(self, batch)
      8     def validation_step(self, batch):
      9         images, labels = batch
---&gt; 10         out = self(images)                    # Generate predictions
     11         loss = F.cross_entropy(out, labels)   # Calculate loss
     12         acc = accuracy(out, labels)           # Calculate accuracy

/opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
   1108         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1109                 or _global_forward_hooks or _global_forward_pre_hooks):
-&gt; 1110             return forward_call(*input, **kwargs)
   1111         # Do not call functions when jit is used
   1112         full_backward_hooks, non_full_backward_hooks = [], []

/tmp/ipykernel_33/3839242004.py in forward(self, xb)
     45 
     46     def forward(self, xb):
---&gt; 47         return self.network(xb)

/opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
   1108         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1109                 or _global_forward_hooks or _global_forward_pre_hooks):
-&gt; 1110             return forward_call(*input, **kwargs)
   1111         # Do not call functions when jit is used
   1112         full_backward_hooks, non_full_backward_hooks = [], []

/opt/conda/lib/python3.7/site-packages/torch/nn/modules/container.py in forward(self, input)
    139     def forward(self, input):
    140         for module in self:
--&gt; 141             input = module(input)
    142         return input
    143 

/opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
   1108         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1109                 or _global_forward_hooks or _global_forward_pre_hooks):
-&gt; 1110             return forward_call(*input, **kwargs)
   1111         # Do not call functions when jit is used
   1112         full_backward_hooks, non_full_backward_hooks = [], []

/opt/conda/lib/python3.7/site-packages/torch/nn/modules/linear.py in forward(self, input)
    101 
    102     def forward(self, input: Tensor) -&gt; Tensor:
--&gt; 103         return F.linear(input, self.weight, self.bias)
    104 
    105     def extra_repr(self) -&gt; str:

RuntimeError: mat1 and mat2 shapes cannot be multiplied (100x2048 and 1024x512)


I would like to analyse images for a defect and thus have a scale of 0 to
1 so as to evaluate the presence of a defect in the sample images
Please help me break it down and understand what is actually going on and how do I determine the right values for the linear to get a single output that will result in a prediction of a 1 or 0


Without going fully through your code, but looking at the comments and error messages, one can see that for the last maxpool layer:
nn.MaxPool2d(2, 2), # output: 512 x 2 x 2

That is, the number of features per image are 512 x 2 x 2 = 1024.
This is then flattened and passed through this linear layer:
nn.Linear(256*2*2, 512),

But this only accepts 256 x 2 x 2 = 1024 input features. This is what causes the mismatch when calling forward for this linear layer. To fix this, change this statement to:
nn.Linear(512*2*2, 512),

