Code Architecture — Group Normalization Notebook
Overview
The notebook implements Group Normalization from scratch in both NumPy and PyTorch, plugs it into a small CNN alongside BatchNorm, and trains both under varying batch sizes to demonstrate GN’s robustness when batch sizes shrink. All computation is GPU-friendly but also runs on CPU.
Section-by-Section Breakdown
1. Imports & Setup
torch,torch.nn,torch.nn.functional,numpy,matplotlibfor visualization- Random seed fixing for reproducibility
- Device detection (GPU if available, else CPU)
2. GroupNorm from Scratch in NumPy
- Function
group_norm_numpy(x, num_groups, gamma, beta, eps=1e-5)- Input:
xis a 4D array of shape (N, C, H, W) - Reshape to (N, G, C//G, H, W) where G = num_groups
- Compute mean μ and variance σ² over the (C//G, H, W) axes for each (N, G) pair
- Normalize: x_norm = (x - μ) / sqrt(σ² + eps)
- Apply per-channel scale γ and shift β
- Reshape back to (N, C, H, W)
- Returns normalized output
- Input:
- Gradient verification: numerical gradient check against PyTorch autograd
- Verify gradients via finite differences on a small random input
- Assert relative error < 1e-4
3. GroupNorm as a PyTorch Module
- Class
GroupNorm(nn.Module)__init__(num_channels, num_groups, eps=1e-5): initializesself.gamma = nn.Parameter(torch.ones(num_channels))andself.beta = nn.Parameter(torch.zeros(num_channels))forward(x): x has shape (N, C, H, W)- Reshape to (N, G, C//G, H, W)
- Compute mean and variance over dims (2, 3, 4) with keepdim=True
- Normalize and apply gain/bias
- Reshape back to (N, C, H, W)
- Key shapes:
- Input: (B, C, H, W) → reshape (B, G, C//G, H, W)
- Mean/var: (B, G, 1, 1, 1)
- Output: (B, C, H, W)
4. BatchNorm2d for Comparison
- Class
BatchNorm2d(nn.Module)— simplified from-scratch version- Normalizes over the batch dimension (dim=0) per channel
- Maintains running mean/var for inference
forward(x): during training, use batch statistics and update running stats; during eval, use running stats- Key difference from GN: statistics computed across (N, H, W) for each channel
5. Normalization Comparison Visualization
- Create a synthetic feature map and show how BN, GN, LayerNorm, and InstanceNorm normalize differently
- Visualize the grouping strategy with a diagram-like output showing which axes each method normalizes over
6. Small CNN Architecture
- Class
ConvBlock(nn.Module)- Conv2d → Normalization → ReLU
- Pluggable normalization: BatchNorm, GroupNorm, or None
- Class
SmallCNN(nn.Module)- 3 conv blocks with max pooling
- Channels: 3 → 16 → 32 → 64
- Global average pooling → linear classifier
- Forward: (B, 3, 32, 32) → conv blocks → (B, 64, 1, 1) → Linear(64, 10)
7. Training Under Varying Batch Sizes
- Dataset: CIFAR-10 (or synthetic if offline)
- Train separate models with BatchNorm and GroupNorm at batch sizes: 32, 8, 4, 2, 1
- Optimizer: SGD with momentum 0.9, lr=0.01
- Loss: CrossEntropyLoss
- Epochs: 5 per configuration (keep runtime short)
- Record final test accuracy for each (norm_type, batch_size) pair
- Key data flow:
Input (B, 3, 32, 32) → ConvBlock1 → (B, 16, 16, 16) → ConvBlock2 → (B, 32, 8, 8) → ConvBlock3 → (B, 64, 4, 4) → AdaptiveAvgPool → (B, 64, 1, 1) → Linear(64, 10) → logits (B, 10)
8. Visualization & Comparison
- Plot 1: Accuracy vs batch size for BatchNorm vs GroupNorm
- Plot 2: Training loss curves at batch_size=2 (showing BN’s instability)
- Plot 3: Feature map statistics (mean/variance) comparison at different batch sizes
- Plot 4: Bar chart of final accuracies across all configurations
9. Weight Standardization (Bonus)
- Brief demonstration of Weight Standardization combined with GN
- Shows how WS+GN can match BN performance even at batch size 1
10. Summary & Analysis
- Print final accuracies for all configurations
- Discuss: GN maintains stable accuracy as batch size shrinks; BN degrades rapidly below batch size 8
- Show that GN with G=1 is equivalent to LayerNorm and G=C is equivalent to InstanceNorm
Key Functions/Classes
| Component | Purpose | |—|—| | group_norm_numpy() | Pure NumPy implementation for gradient verification | | GroupNorm(nn.Module) | Reusable PyTorch GroupNorm module | | BatchNorm2d(nn.Module) | From-scratch BatchNorm for comparison | | ConvBlock | Conv + Norm + ReLU building block | | SmallCNN | 3-block CNN for image classification | | train_model() | Training loop with configurable batch size and norm type |
Data Flow & Shapes
Input: (B, 3, 32, 32) # CIFAR-10 images
↓ ConvBlock1: Conv(3→16, 3x3, pad=1) + Norm + ReLU + MaxPool(2)
(B, 16, 16, 16)
↓ ConvBlock2: Conv(16→32, 3x3, pad=1) + Norm + ReLU + MaxPool(2)
(B, 32, 8, 8)
↓ ConvBlock3: Conv(32→64, 3x3, pad=1) + Norm + ReLU + MaxPool(2)
(B, 64, 4, 4)
↓ AdaptiveAvgPool2d(1)
(B, 64, 1, 1) → flatten → (B, 64)
↓ Linear(64, 10)
logits: (B, 10)
↓ CrossEntropy
loss: scalar
Deliberate Simplifications vs Full Paper
- Small CNN — 3 conv blocks with 16/32/64 channels (paper uses ResNet-50 with 50 layers)
- CIFAR-10 — 32×32 images (paper uses ImageNet at 224×224)
- 5 epochs — short training to keep Kaggle runtime under 30 min (paper trains for full schedules)
- No detection/segmentation experiments — paper shows COCO detection and Kinetics video results; we focus on classification accuracy vs batch size
- No transfer learning — paper demonstrates GN transferring from pre-training to fine-tuning; we train from scratch
- Fixed group count — we use G=32 as default (paper also uses 32 for ResNet-50); we briefly explore other G values but don’t do a full sweep
- No running statistics for GN — GN doesn’t need them by design; we highlight this as an advantage rather than implementing a full eval-mode comparison