Ismail Ben Alla

U-Net Image Segmentation

Six Segmentation Variants Measured on the Same Data

Computer vision · Oct 2026 · Completed

Which U-Net design choices actually matter: skip connections, pooling, block depth and residuals, each one a flag and a number.

Built withPyTorchtorchvisionpytestMatplotlibNumPyKaggleGoogle Colab

U-Net Image Segmentation — overview

Overview

This started as a computer-vision coursework notebook that asked four questions about U-Net: does max-pooling beat a strided convolution, how much do skip connections bring, how does an encoder-decoder compare with a fully connected network, and how should the inference threshold be chosen. I rebuilt it as a package in which each question is one flag, the models are small (1 to 2M parameters, minutes per run on a CPU) and every answer is re-measured with IoU and Dice instead of pixel accuracy.

Six presets share one EncoderDecoder class: the plain U-Net, a strided-conv version, a single-conv version, a residual version, a SegNet-like model with no skip connections, and a fully connected baseline made of Linear layers only. They all train on the same synthetic shapes and on a subset of Oxford-IIIT Pet, with BCE + Dice loss, and are scored from one confusion matrix. A threshold sweep on the validation split picks the cutoff, never the test split.

On the shapes the plain U-Net reaches test IoU 0.560 against 0.422 for strided convolutions and 0.489 without skips; the fully connected model scores 0.102 with ten times the parameters. On the pet photos the residual U-Net leads at 0.679, then U-Net 0.641, no skips 0.630 and fully connected 0.524. Porting the notebook also exposed that its validation and test sets were augmented, its threshold sweep ran over 40 to 80 instead of 0.40 to 0.80, and its fully connected model ended in a ReLU that forbade negative logits.

The question

What do skip connections, max-pooling, double convolutions and residual blocks each buy a segmentation network, when every variant is trained on the same data and scored with the same metric?

Key features

How it works

  1. Down-sample four times

    A stem ConvBlock followed by four down steps halves the resolution each time, by a fixed 2 × 2 max-pool or a learned 3 × 3 stride-2 convolution, with one or two convolutions per block and an optional residual path.

  2. Up-sample and concatenate

    Four ConvTranspose 2 × 2 steps bring the bottleneck back to full size; with skips on, each step concatenates the encoder map of the same size, and with skips off the decoder only sees the bottleneck.

  3. Or skip the convolutions

    The fully connected baseline flattens the image, passes it through a stack of Linear layers and reshapes the output, so it has no locality and no hierarchy at all.

  4. Train with BCE + Dice

    AdamW with warm-up and cosine decay, batch 16, 96 px images; BCE scores every pixel and soft Dice scores the overlap, which pushes the probabilities toward 0 or 1.

  5. Score and choose the threshold

    Probabilities above a threshold become the mask; IoU, Dice, precision and recall are read off one confusion matrix, and the threshold is swept on the validation split before the test split is scored.

Examples

U-Net on the synthetic shapes, one frame per epoch: green is correct object pixels, red false positives, blue missed pixels. The untrained network paints almost everything red; by the last epoch the mask follows the outlines.
The same U-Net on Oxford-IIIT Pet photos, epoch by epoch: the mask moves onto the animal within a few epochs, and this re-run reproduced the table's test IoU of 0.641 exactly.
The same test images through every variant, with the per-image IoU below each panel. The strided model misses whole small triangles, the no-skip model turns shapes into rounded blobs, and the fully connected model paints noise where objects tend to be.
The same test images through every variant, with the per-image IoU below each panel. The strided model misses whole small triangles, the no-skip model turns shapes into rounded blobs, and the fully connected model paints noise where objects tend to be.
Pet photos through U-Net, residual U-Net, the no-skip model and the fully connected baseline. The U-Nets find the animal (recall about 0.85) but also paint background of a similar colour; the fully connected model predicts a centred blob whatever the pose.
Pet photos through U-Net, residual U-Net, the no-skip model and the fully connected baseline. The U-Nets find the animal (recall about 0.85) but also paint background of a similar colour; the fully connected model predicts a centred blob whatever the pose.
Validation IoU and training loss per epoch for the six variants on the shapes. The fully connected model's IoU falls after epoch 2 as it starts memorising the 600 training images.
Validation IoU and training loss per epoch for the six variants on the shapes. The fully connected model's IoU falls after epoch 2 as it starts memorising the 600 training images.

Input

unetseg-data shapes && python scripts/compare_all.py --data data/shapes --epochs 6 --max-train 600 --threads 1 --out runs/shapes

Output

test IoU: unet-single 0.660, unet-residual 0.633, unet 0.560, segnet 0.489, unet-strided 0.422, fcn 0.102 (Dice 0.796, 0.775, 0.718, 0.657, 0.593, 0.184); pixel accuracy above 0.83 for every model, including fcn.

The run behind the shapes table: 600 training images at 96 px, 6 epochs, BCE + Dice, 2 to 11 minutes per model on one CPU thread.

Tech stack

What I learned

Limitations

Keywords

U-Net · image segmentation · binary segmentation · skip connections · max-pooling vs strided convolution · residual blocks · SegNet · fully convolutional network · Dice loss · IoU · threshold sweep · Oxford-IIIT Pet · PyTorch · computer vision · deep learning