Semantic Segmentation and U-Net Skip Connections
Pooling throws resolution away on purpose, to build context. Pixel-level segmentation needs that resolution back. U-Net's skip connections are how it gets it.
Downsample Depth
a 16×16 mask, majority-vote 2×2 pooling per level, nearest-neighbour upsampling back
Ground Truth vs Reconstructions
—Pixel Accuracy
Overview
The idea in brief
Semantic splitting labels each pixel with a class, not just the pic as a whole. A CNN sorter's usual move. pool down repeatedly to build up wide receptive fields and semantic context. Is just what a splitting decoder then has to undo, pixel by pixel, to give a full-resolution output mask.
U-Net is the design that made this real. It has an encoder (the downward path) that contracts the pic through convolutions and pooling, building up what each region means while shrinking the spatial resolution. It has a decoder (the upward path) that expands the resolution back to the first size with transposed convolutions or upsampling. The key idea is the skip links between matching levels of the encoder and decoder: high-res spatial detail from the encoder is joined with the semantic data from the decoder. So the network can draw precise edges rather than blobby outlines.
The output is a tensor with the same height and width as the input pic and one channel per class. At each pixel the net predicts a chance spread over classes. And the class with the highest chance turns that pixel's label. The loss function is often cross-entropy found pixel by pixel, though class imbalance (roads are common, pedestrians are rare) often needs a weighted variant or dice loss.
Semantic splitting differs from instance splitting. Semantic splitting labels each pixel with a class but cannot distinguish two cars from each other. Both are "car". Instance splitting (Mask R-CNN) assigns a split mask to each single object. Panoptic splitting mixes both: each pixel gets a class label and an instance id. U-Net and its variants (U-Net++, Attention U-Net, nnU-Net) remain the dominant design for medical imaging, satellite imagery and any task where pixel-level score matters more than real-time speed.
Pooling throws resolution away on purpose, to build context.
In this guide
- The idea in brief
- What pooling really destroys
- Labelling each pixel
- U-Net's answer: go down, come back up, and remember
- Why it works on small datasets
- Why U-Net has to be a U
- Guided tour
- What this simplification doesn't show
- What to remember
- Losses for splitting
- Options and refinements
- Common mistakes
- Questions people ask
- Recap in one screen
Semantic Segmentation and U-Net: A Practical Guide
Classification asks what's in the image. Segmentation asks, for every single pixel.
The idea in brief
Semantic splitting labels each pixel with a class, not just the pic as a whole. A CNN sorter's usual move. pool down repeatedly to build up wide receptive fields and semantic context. Is just what a splitting decoder then has to undo, pixel by pixel, to give a full-resolution output mask.
U-Net is the design that made this real. It has an encoder (the downward path) that contracts the pic through convolutions and pooling, building up what each region means while shrinking the spatial resolution. It has a decoder (the upward path) that expands the resolution back to the first size with transposed convolutions or upsampling. The key idea is the skip links between matching levels of the encoder and decoder: high-res spatial detail from the encoder is joined with the semantic data from the decoder. So the network can draw precise edges rather than blobby outlines.
The output is a tensor with the same height and width as the input pic and one channel per class. At each pixel the net predicts a chance spread over classes. And the class with the highest chance turns that pixel's label. The loss function is often cross-entropy found pixel by pixel, though class imbalance (roads are common, pedestrians are rare) often needs a weighted variant or dice loss.
Semantic splitting differs from instance splitting. Semantic splitting labels each pixel with a class but cannot distinguish two cars from each other. Both are "car". Instance splitting (Mask R-CNN) assigns a split mask to each single object. Panoptic splitting mixes both: each pixel gets a class label and an instance id. U-Net and its variants (U-Net++, Attention U-Net, nnU-Net) remain the dominant design for medical imaging, satellite imagery and any task where pixel-level score matters more than real-time speed.
What pooling really destroys
Max or bulk pooling is a real, lossy step: a 2×2 block of pixels turns one pixel. And whatever varied within that block is gone for good. Naively upsampling the coarse result back up. Nearest-neighbour or bilinear, with nothing else. Cannot recover that lost detail, since the information needed to recover it no longer exists anywhere in the coarse map. U-Net's skip connections route the encoder's full-resolution feature maps right across to the matching decoder stage. So the fine spatial detail pooling destroyed never has to be reconstructed from nothing. It's simply still there, carried across.
Labelling each pixel
Sorting gives one label per pic. Detection gives a box per object. Semantic splitting gives a label to each single pixel. Road, building, sky, person. Giving an output the same size as the input.
Three tied tasks are easy to confuse:
| Task | Output | Distinguishes individual objects? |
|---|---|---|
| Semantic segmentation | A class per pixel | No — all cars are "car" |
| Instance segmentation | A mask per object | Yes |
| Panoptic segmentation | Both, combined | Yes, plus background classes |
The architectural trouble is a genuine tension. Recognising what something is needs a wide view and abstract features. It means downsampling. Knowing just which pixels it occupies needs full resolution. It downsampling destroys.
U-Net's answer: go down, come back up, and remember
U-Net is shaped like a U. And the shape is the idea.
The encoder (the left side) is a standard convolutional stack: convolutions and downsampling, halving the resolution and doubling the channels at each stage. By the bottom it has a rich, abstract, low-resolution form. It knows what is in the pic.
The decoder (the right side) upsamples back to full resolution, halving the channels at each stage.
The skip connections are what make it work. At each level, the encoder's feature map is concatenated onto the decoder's. So the decoder has both the semantic data from the deep path and the fine spatial detail from the matching shallow one.
Without those links, the output is correct in group and blurry at the edges, since the edge data was thrown away in downsampling and there is no way to invent it back. With them, edges are sharp.
Note that U-Net concatenates rather than adds, unlike ResNet. Joining keeps both sources apart and lets the next convolution decide how to mix them.
Why it works on small datasets
U-Net was designed for biomedical pics. There a dataset might hold thirty annotated cases. A few of its properties make that feasible.
- It is fully convolutional, with no dense layers. So it accepts any input size and has fairly few params.
- Heavy tweaking — very elastic deformation. It is realistic for tissue — multiplies the good dataset.
- Each pixel is a training case. A single 512×512 pic gives 262,144 labelled pixels. It is why so few pics can be enough.
- Patch-based training lets large pics be handled in tiles, with overlap to avoid edge artefacts.
The encoder is now often replaced with a pretrained backbone. ResNet, EfficientNet — which improves results more. That variant is what most splitting libraries give you by default.
Why U-Net has to be a U
A splitting network needs both a wide view and a precise one. And downsampling gives you the first at the cost of the second. U-Net's answer is the skip connection. And this measures just what it recovers -- by building the same decoder with and without it.
Building on the same setup, the next block shows the left cases.
The next block covers the left steps.
The next block continues with the left demonstrations.
Building on the same setup, the next block shows the left cases.
Guided tour
- Read all three masks at 1 downsampling level. The no-skip reconstruction is now visibly blockier at the edge than the ground truth circle.
- Push depth to 3 levels. The no-skip mask's pixel score drops more. Each extra pooling level throws away more edge detail that nearest-neighbour upsampling has no way to invent back.
- Check against the with-skip mask. It matches the ground truth just, at any depth. Since this simplified version literally routes the first full-resolution mask across, rather than a pooled-and-corrupted feature map.
What this simplification doesn't show
A real U-Net's skip connections carry learned feature maps across, not the raw ground-truth labels. Its decoder still has to learn to fuse coarse semantic features with fine spatial ones. And that fusion is imperfect. A trained U-Net does not hit 100% pixel score just since it has skip connections. What this toy shows honestly is the underlying trick: recovering resolution that pooling destroyed by carrying it across right, rather than trying to hallucinate it back from a coarse map alone. That trick is just why U-Net needs skip connections at all.
What to remember
Downsampling for context and needing pixel-precise output are in direct tension. The same pooling that builds semantic grasp destroys the spatial detail a splitting mask needs back. Skip links resolve that tension not by improving the upsampling step. But by making it partly unneeded: the fine detail rides across the bridge instead of being rebuilt from a coarse map that no longer holds it.
Losses for splitting
Splitting has a trait problem: class imbalance within the pic. A tumour might occupy 1% of the pixels. And a net that predicts "background" all over scores 99% pixel score.
The standard losses respond to this right:
| Loss | Behaviour |
|---|---|
| Cross-entropy | Per-pixel classification; dominated by the majority class |
| Weighted cross-entropy | Rare classes weighted up |
| Dice loss | Optimises overlap directly; good for small foregrounds |
| Focal loss | Down-weights easy pixels, focuses on hard ones |
| Dice + cross-entropy | The common practical combination |
Dice loss is derived from the Dice coefficient, 2|A∩B| / (|A|+|B|). And since it is a ratio it is largely insensitive to how much background there is. Mixing it with cross-entropy is the most common default in medical splitting, since the two have complementary gradient behaviour.
For test, mean IoU across classes is the standard metric, with the Dice coefficient (the same to F1 over pixels) more common in medical work. Pixel score is reported at times and should be treated with the same suspicion as score on any imbalanced problem.
Options and refinements
DeepLab uses dilated convolutions to widen the receptive field without downsampling at all, plus an atrous spatial pyramid that looks at a few dilation rates in parallel. Strong on natural scenes.
FCN was the earlier fully-convolutional way: take a sorter, replace the dense layers with convolutions, and upsample. Simpler and less precise at edges.
SegFormer and Mask2Former bring transformers to splitting, with strong results at more training cost.
Segment Anything (SAM) is a promptable foundation net that gives high-quality masks with no task-set training. And is increasingly used to accelerate annotation rather than replace task-set nets.
For most applied projects, a U-Net with a pretrained encoder stays the pragmatic starting point. And segmentation_models_pytorch gives it in a few lines.
Common mistakes
- Resizing masks with bilinear interpolation. This blends label vals into meaningless intermediates — class 3.7. Always use nearest-neighbour for masks.
- Tweaking the pic and not the mask, or applying other random params to each.
- Reporting pixel score on an imbalanced problem.
- Ignoring the ignore label. Many datasets mark unlabelled pixels with a special value that must be excluded from the loss.
- Tiling without overlap, which gives visible seams at tile edges.
- Forgetting that the output needs an argmax across the channel dimension to turn a label map.
Questions people ask
How many annotated pics do I need? Tens can work with heavy tweaking and a pretrained encoder. Hundreds for reliable results on natural scenes.
Why concatenate instead of add in the skip connections? Concatenation keeps both feature sets intact and lets the next convolution learn how to weigh them. Addition assumes they are right comparable.
What input size should I use? Any multiple of the total downsampling factor — often 32. Mismatched sizes cause shape errors in the decoder.
How do I handle very large pics? Tile with overlap and blend the predictions. Or downsample if fine detail is not needed.
Can U-Net do instance splitting? Not right. It does not split touching objects of the same class. Mask R-CNN or a watershed post-handling step handles that.
Is U-Net outdated? No. It stays the default in medical imaging and is a strong, cheap baseline all over else.
Recap in one screen
- Semantic splitting assigns a class to each pixel. The output is the same size as the input.
- The tension is between semantic depth (needs downsampling) and spatial precision (needs resolution).
- U-Net downsamples, upsamples. And concatenates matching encoder features into the decoder. Which is what keeps edges sharp.
- It works on tiny datasets since each pixel is a training case and tweaking goes a long way.
- Use Dice plus cross-entropy for imbalanced foregrounds, test with mean IoU. And never interpolate masks bilinearly.