U-Net and V-Net
U-Net passes fine spatial details directly from the encoder to the decoder via skip connections, enabling crisp pixel segmentation even with scarce data.
Why Does This Exist?
In biomedical imaging, annotated data is scarce: a clinical trial may offer dozens of scans annotated by specialists where natural-image datasets offer millions of photos. Standard classifiers fail twice here. Successive pooling destroys high-frequency boundaries such as membranes and tumor margins, so naive upsampling returns blurry blobs. And a small lesion can cover under one percent of voxels, so plain cross-entropy gradients drown in background and the network predicts empty masks.
U-Net (Ronneberger and coauthors, 2015) fixes localization with a symmetric encoder-decoder plus lateral skip connections that copy high-resolution features straight across to the decoder. V-Net (Milletari and coauthors, 2016) extends the idea to 3D volumes with residual stages and a differentiable Dice loss that keeps gradients alive for tiny foregrounds. This page covers the skip mechanism, the 3D extension, and the loss. The dense-prediction setup lives in semantic segmentation, the fully convolutional baseline in fully convolutional networks, and the loss function on its own in dice loss. The U-Net segmentation visual pairs with this page as its picture.
Think of It Like This
A translation desk with the original pages on clips
A researcher condenses each dense manuscript page into a short summary card and hands the cards to a typist. The typist grasps the themes but must guess every exact letter shape, so the rebuilt pages look blurry. U-Net clips each original page opposite the typist: themes come from the summary while exact strokes are copied straight from the source.
Summaries are the bottleneck features, the clipped pages are the skip connections, and the typist is the decoder fusing both. Where it stops: a desk with every draft ever written would bury the typist, just as skips without channel fusion would flood the decoder with unfiltered detail.
How It Actually Works
The U-shaped blueprint
The encoder repeats blocks of two convolutions plus ReLU followed by max pooling with stride 2, mapping to : channels double while each side halves. The bottleneck holds the coarsest map (for example 512 channels at ) with global context. The decoder reverses the trip: a transposed convolution halves channels and doubles sides, mapping to . Then comes the lateral skip: the upsampled map is concatenated with the matching encoder map, , and two convolutions fuse detail with context. A final convolution plus softmax or sigmoid emits the class scores per pixel. Here is channel count, and are spatial sides, and is the class count.
V-Net in 3D
V-Net processes whole volumes () with kernels instead of slices, replaces max pooling with strided convolutions that learn the downsampling, and adds residual shortcuts inside each stage, where is the stage transform and is its input. The residual path keeps gradients flowing through deep volumetric stacks that plain chains would stall.
Dice loss for tiny foregrounds
With the predicted probability and the binary truth at voxel , the soft Dice score is with smoothing constant , and the loss is . Because the denominator counts predicted plus true foreground instead of the whole volume, microscopic structures keep strong gradients where cross-entropy would vanish into background.
Worked Dice numbers
Take ground truth and predictions . The numerator is . The denominator is . So and . Near-zero foreground predictions collapse the numerator to against a denominator near , giving and loss : the omission is punished regardless of background size.
Code
The point of this snippet is the loss arithmetic from the worked example plus the skip shape contract, both replayed in plain Python so the numbers can be checked.
p = [0.8, 0.7, 0.1, 0.2]g = [1.0, 1.0, 0.0, 0.0]
num = 2.0 * sum(pi * gi for pi, gi in zip(p, g))den = sum(pi * pi for pi in p) + sum(gi * gi for gi in g)dice = num / denprint(round(dice, 4))# -> 0.9434print(round(1.0 - dice, 4))# -> 0.0566
enc = (128, 32, 32) # (channels, height, width) from the encoderdec = (128, 32, 32) # upsampled decoder map at the same stageprint(enc[1:] == dec[1:])# -> TrueThe score and loss match the hand computation. The shape check is the skip contract: concatenation is legal only when the two spatial maps agree exactly.
Watch Out For
Shape crashes at skip concatenation
Original U-Net used unpadded convolutions, so encoder maps arrived larger than decoder maps and needed center cropping before concatenation. The symptom is a concat error naming mismatched heights at one stage. Fix it with padded convolutions and input sides divisible by or , so every upsampling reproduces its encoder stage exactly.
Dice loss misbehaving on empty masks
Patches with no foreground make the Dice denominator tiny, so the score swings wildly and the gradient spikes. The symptom is NaN or plateaued loss on background-heavy volumes. Fix it with the smoothing constant and by training Dice jointly with cross-entropy rather than alone.
The Quick Version
- U-Net concatenates encoder maps into the decoder, fusing fine where with deep what for sharp masks.
- V-Net extends the design to 3D with volumetric kernels, strided convolutions, and residual stages.
- Dice loss divides by predicted plus true foreground, so tiny structures keep strong gradients.
- Predictions against truth score with loss .
- Skip maps must match spatially before concatenation, and empty masks need smoothing plus cross-entropy.