AI · Deep Learning · Computer Vision · CNN
OUTTA Basic — PyTorch CNN and Handwritten-Digit Error Analysis
2026-08-01 · updated 2026-08-01 · Hyeongrok Ryu
I traced convolution shapes and read retained loss, accuracy, correct-sample, and misclassification plots together.
- Type / level
- study-note · beginner
- Tools
- Python, PyTorch, Matplotlib
A checkpoint in the study sequence for this note.
A checkpoint in the study sequence for this note.
A checkpoint in the study sequence for this note.
A checkpoint in the study sequence for this note.
Start with convolution shapes
I studied a CNN through input and output shapes instead of memorizing filter diagrams. After checking kernel, stride, and padding in the 92-page CNN module, I used
H(out) = floor((H(in) + 2P − K) / S) + 1
When a notebook tensor did not match the Linear input after flattening, I printed intermediate shapes and followed how convolution and pooling reduced the spatial dimensions.
Inspect inputs first
The 14-page Dataset and DataLoader module reminded me to plot samples beside labels before batching. The same digit can vary greatly in stroke width, tilt, and position. Accuracy alone cannot explain which variations are difficult.

Read loss and accuracy together
My edited CNN notebook had two code cells that differed from the base, plus 17 retained output objects and five figures. Its stored curves show an overall loss decrease and high accuracy, but a small validation set can move sharply when only one or two samples change.


Correct and incorrect examples
The correctly predicted 1 has a clear vertical stroke. In the error grid, open loops, connected strokes, and tilted lines lead to confusions such as 5→3, 4→9, and 7→9. Before adding layers, I would check normalization, cropping, and augmentation in that order.


Minimal CNN forward pass
class SmallCNN(torch.nn.Module):
def __init__(self):
super().__init__()
self.features = torch.nn.Sequential(
torch.nn.Conv2d(1, 16, kernel_size=3, padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(2),
torch.nn.Conv2d(16, 32, kernel_size=3, padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(2),
)
self.classifier = torch.nn.Linear(32 * 7 * 7, 10)
def forward(self, x):
features = self.features(x)
return self.classifier(features.flatten(1))
Connection to transfer learning
The 26-page transfer-learning module separated training a small CNN from scratch from using a pretrained feature extractor. I wrote down the order as matching channel count, resize, and normalization to the backbone, training the classifier first, and leaving partial unfreezing for a later step. I have not counted that sequence as a fresh run here.
Previous and next
Sources used
- CNN — course-pdf; convolution, pooling, and image classification
- Dataset and DataLoader — course-pdf; batches and data splits
- Transfer Learning — course-pdf; feature extraction and fine-tuning