Level 5 — MasteryConvolutional Neural Networks

Convolutional Neural Networks

2 minutes60 marksprintable — key stays hidden on paper

Time limit: 2 hours 30 minutes Total marks: 60 Instructions: Answer ALL three questions. Show full derivations; state assumptions. Partial credit for correct reasoning.


Question 1 — Spatial Arithmetic, Receptive Fields & Compute Budget (20 marks)

A feed-forward CNN backbone processes RGB inputs of size 224×224×3224\times224\times3. The stack is:

Layer Type Kernel Stride Padding Dilation Out channels
L1 Conv 7×77\times7 2 3 1 64
L2 MaxPool 3×33\times3 2 1 1 64
L3 Conv 3×33\times3 1 2 2 128
L4 Conv 3×33\times3 1 1 1 128

(a) Using the general spatial-output formula, derive the height/width of the feature map after each layer L1–L4. State the formula you use, including the dilation term. (6)

(b) For a convolution the effective kernel size under dilation dd is keff=d(k1)+1k_{\text{eff}} = d(k-1)+1. Prove, by unrolling the recurrence for the receptive-field size rr_\ell and jump jj_\ell, that r=r1+(keff,1)j1,j=j1s,r_\ell = r_{\ell-1} + (k_{\text{eff},\ell}-1)\,j_{\ell-1}, \qquad j_\ell = j_{\ell-1}\, s_\ell, then compute the receptive field (in input pixels) of a single unit at the output of L4. (7)

(c) Count the number of multiply–accumulate operations (MACs) for layer L3 only, treating the dilated conv as a standard conv over its output spatial grid. Show your working: MACs == (output positions) ×\times (output channels) ×\times (kernel elements) ×\times (input channels). (4)

(d) Explain in 2–3 sentences why replacing L3's single dilated 3×33\times3 by two stacked non-dilated 3×33\times3 convs changes both parameter count and receptive-field growth. (3)


Question 2 — Residual Learning: Gradient Flow Proof + Code (22 marks)

Consider a residual block y=x+F(x;W)\mathbf{y} = \mathbf{x} + \mathcal{F}(\mathbf{x};W) and a plain block y=H(x;W)\mathbf{y} = \mathcal{H}(\mathbf{x};W).

(a) For a stack of LL residual blocks x+1=x+F(x)\mathbf{x}_{\ell+1} = \mathbf{x}_\ell + \mathcal{F}_\ell(\mathbf{x}_\ell), prove that xL=x+i=L1Fi(xi),\mathbf{x}_L = \mathbf{x}_{\ell} + \sum_{i=\ell}^{L-1}\mathcal{F}_i(\mathbf{x}_i), and hence derive the gradient of a loss E\mathcal{E} w.r.t. x\mathbf{x}_\ell: Ex=ExL(1+xi=L1Fi(xi)).\frac{\partial \mathcal{E}}{\partial \mathbf{x}_\ell} = \frac{\partial \mathcal{E}}{\partial \mathbf{x}_L}\left(1 + \frac{\partial}{\partial \mathbf{x}_\ell}\sum_{i=\ell}^{L-1}\mathcal{F}_i(\mathbf{x}_i)\right). Explain precisely why the additive "11" term mitigates vanishing gradients. (8)

(b) A "bottleneck" residual block for ResNet-50 uses, on a CC-channel input at spatial size H×WH\times W: a 1×11\times1 conv reducing to C/4C/4, a 3×33\times3 conv keeping C/4C/4, and a 1×11\times1 conv expanding back to CC. Derive the total parameter count (weights only, ignore bias/BN) as a function of CC, and compare it to a "basic" block of two 3×33\times3 convs each keeping CC channels. For C=256C=256, give both numbers. (6)

(c) Write a PyTorch nn.Module implementing the bottleneck block with a projection shortcut used when input/output channels differ or stride >1>1. Include BatchNorm and ReLU in the standard ResNet ordering, and ensure the addition is followed by the final activation. (8)


Question 3 — Detection/Segmentation Design + IoU Physics-of-Sampling (18 marks)

(a) Two axis-aligned bounding boxes are given in (x1,y1,x2,y2)(x_1,y_1,x_2,y_2) corner format: A=(10,20,60,80),B=(30,40,90,100).A=(10,20,60,80), \qquad B=(30,40,90,100). Compute the Intersection-over-Union (IoU). Show intersection area, union area, and the final value as a fraction and a decimal to 3 d.p. (5)

(b) Contrast YOLO (single-shot, grid regression) with a two-stage R-CNN family detector along THREE axes: (i) how region proposals arise, (ii) speed/accuracy trade-off, (iii) how each handles multiple objects per spatial location. Then state, with justification, which you would choose for a 30 FPS embedded drone. (6)

(c) In U-Net, downsampling loses spatial resolution. Explain the mechanism of skip connections between the contracting and expanding paths, and why concatenation (as in U-Net) differs functionally from addition (as in ResNet). Give one reason data augmentation (e.g. elastic deformation) is especially important for biomedical segmentation. (4)

(d) A segmentation network outputs logits; you use a combined loss L=LCE+λ(1Dice)\mathcal{L}=\mathcal{L}_{CE}+\lambda(1-\text{Dice}). State the Dice coefficient formula for predicted mask PP and ground truth GG, and explain in one sentence why Dice is preferred over pixel accuracy for class-imbalanced masks. (3)

Answer keyMark scheme & solutions

Question 1

(a) Formula (per spatial dim), effective kernel keff=d(k1)+1k_{\text{eff}}=d(k-1)+1: O=I+2Pkeffs+1.O=\left\lfloor \frac{I + 2P - k_{\text{eff}}}{s}\right\rfloor + 1. (1 mark for correct formula incl. dilation.)

  • L1: k=7,P=3,s=2,d=1keff=7k=7,P=3,s=2,d=1\Rightarrow k_{\text{eff}}=7: (224+67)/2+1=223/2+1=111+1=112\lfloor(224+6-7)/2\rfloor+1=\lfloor223/2\rfloor+1=111+1=112. → 112×112×64. (1.5)
  • L2: k=3,P=1,s=2k=3,P=1,s=2: (112+23)/2+1=111/2+1=55+1=56\lfloor(112+2-3)/2\rfloor+1=\lfloor111/2\rfloor+1=55+1=56. → 56×56×64. (1.5)
  • L3: k=3,d=2keff=2(2)+1=5k=3,d=2\Rightarrow k_{\text{eff}}=2(2)+1=5; P=2,s=1P=2,s=1: (56+45)/1+1=55+1=56\lfloor(56+4-5)/1\rfloor+1=55+1=56. → 56×56×128. (1)
  • L4: k=3,P=1,s=1,d=1keff=3k=3,P=1,s=1,d=1\Rightarrow k_{\text{eff}}=3: (56+23)/1+1=55+1=56\lfloor(56+2-3)/1\rfloor+1=55+1=56. → 56×56×128. (1)

(b) Derivation (recurrence unrolling, 4 marks). Initialize r0=1r_0=1, j0=1j_0=1. A layer with effective kernel keffk_{\text{eff}} and stride ss: each output unit sees keffk_{\text{eff}} consecutive units of the previous map, and adjacent previous units are spaced by the previous jump j1j_{\ell-1} in input pixels. Extra span added =(keff1)j1=(k_{\text{eff}}-1)j_{\ell-1}, giving r=r1+(keff,1)j1,j=j1s.r_\ell=r_{\ell-1}+(k_{\text{eff},\ell}-1)j_{\ell-1}, \qquad j_\ell=j_{\ell-1}s_\ell.

Computation (3 marks). Jumps: j0=1j_0=1; j1=12=2j_1=1\cdot2=2; j2=22=4j_2=2\cdot2=4; j3=41=4j_3=4\cdot1=4; j4=41=4j_4=4\cdot1=4. RF (keffk_{\text{eff}}: L1=7, L2=3, L3=5, L4=3):

  • r1=1+(71)1=7r_1=1+(7-1)\cdot1=7
  • r2=7+(31)2=7+4=11r_2=7+(3-1)\cdot2=7+4=11
  • r3=11+(51)4=11+16=27r_3=11+(5-1)\cdot4=11+16=27
  • r4=27+(31)4=27+8=35r_4=27+(3-1)\cdot4=27+8=\mathbf{35} input pixels. (final 1 mark)

(c) L3 output grid 56×56=313656\times56=3136 positions; out ch =128=128; kernel elems =3×3=9=3\times3=9; in ch =64=64. MACs=3136×128×9×64=231,211,0082.31×108.\text{MACs}=3136\times128\times9\times64 = 231{,}211{,}008 \approx 2.31\times10^8. (2 setup, 2 result)

(d) Two stacked non-dilated 3×33\times3 convs have keff=3k_{\text{eff}}=3 each → RF grows +2+2=4+2+2=4 (contiguously sampled), vs one dilated conv keff=5k_{\text{eff}}=5 → RF grows +4+4 but with gaps (sparse/gridding sampling). Parameters: two 3×33\times3 layers cost 2×(9CinCout)2\times(9C_{in}C_{out}) ≈ double one dilated layer, but give denser coverage and extra nonlinearity. (3: RF density + param comment)


Question 2

(a) (5 marks derivation, 3 explanation.) By induction on the recurrence xi+1=xi+Fi(xi)\mathbf{x}_{i+1}=\mathbf{x}_i+\mathcal{F}_i(\mathbf{x}_i): summing telescopically from i=i=\ell to L1L-1, xL=x+i=L1Fi(xi).\mathbf{x}_L=\mathbf{x}_\ell+\sum_{i=\ell}^{L-1}\mathcal{F}_i(\mathbf{x}_i). Differentiate via chain rule: Ex=ExLxLx=ExL(1+xiFi).\frac{\partial\mathcal{E}}{\partial\mathbf{x}_\ell}=\frac{\partial\mathcal{E}}{\partial\mathbf{x}_L}\frac{\partial\mathbf{x}_L}{\partial\mathbf{x}_\ell}=\frac{\partial\mathcal{E}}{\partial\mathbf{x}_L}\Big(1+\tfrac{\partial}{\partial\mathbf{x}_\ell}\textstyle\sum_i\mathcal{F}_i\Big). Why: the constant "1" provides an identity (shortcut) path so E/xL\partial\mathcal{E}/\partial\mathbf{x}_L propagates undiminished to any earlier layer even if the F\mathcal{F}-Jacobian product is near zero; the gradient cannot fully vanish because the bracket is 1+(something)1+(\text{something}), never a product of many small factors.

(b) (6 marks.) Bottleneck weights (kernel²·Cin·Cout):

  • 1×11\times1: 1C(C/4)=C2/41\cdot C\cdot(C/4)=C^2/4
  • 3×33\times3: 9(C/4)(C/4)=9C2/169\cdot(C/4)\cdot(C/4)=9C^2/16
  • 1×11\times1: 1(C/4)C=C2/41\cdot(C/4)\cdot C=C^2/4

Total =C24+9C216+C24=4C2+9C2+4C216=17C216=\dfrac{C^2}{4}+\dfrac{9C^2}{16}+\dfrac{C^2}{4}=\dfrac{4C^2+9C^2+4C^2}{16}=\dfrac{17C^2}{16}.

Basic block (two 3×33\times3, C→C): 2×9C2=18C22\times9C^2=18C^2. For C=256C=256: bottleneck =1765536/16=69,632...=17×4096=69,632=17\cdot65536/16=69{,}632\cdot... =17\times4096=\mathbf{69{,}632}; basic =18×65536=1,179,648=18\times65536=\mathbf{1{,}179{,}648}. Bottleneck ≈ 17× cheaper. (3 derivation, 3 numbers)

(c) (8 marks: correct convs 3, BN/ReLU order 2, shortcut logic 2, final add+ReLU 1.)

import torch.nn as nn
 
class Bottleneck(nn.Module):
    expansion = 4
    def __init__(self, in_ch, mid_ch, stride=1):
        super().__init__()
        out_ch = mid_ch * self.expansion
        self.conv1 = nn.Conv2d(in_ch, mid_ch, 1, bias=False)
        self.bn1   = nn.BatchNorm2d(mid_ch)
        self.conv2 = nn.Conv2d(mid_ch, mid_ch, 3, stride=stride,
                               padding=1, bias=False)
        self.bn2   = nn.BatchNorm2d(mid_ch)
        self.conv3 = nn.Conv2d(mid_ch, out_ch, 1, bias=False)
        self.bn3   = nn.BatchNorm2d(out_ch)
        self.relu  = nn.ReLU(inplace=True)
        self.shortcut = nn.Sequential()
        if stride != 1 or in_ch != out_ch:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_ch, out_ch, 1, stride=stride, bias=False),
                nn.BatchNorm2d(out_ch))
    def forward(self, x):
        out = self.relu(self.bn1(self.conv1(x)))
        out = self.relu(self.bn2(self.conv2(out)))
        out = self.bn3(self.conv3(out))
        out += self.shortcut(x)      # add BEFORE final activation
        return self.relu(out)

Question 3

(a) (5 marks.) Intersection corners: x=[max(10,30),min(60,90)]=[30,60]x=[\max(10,30),\min(60,90)]=[30,60], width =30=30; y=[max(20,40),min(80,100)]=[40,80]y=[\max(20,40),\min(80,100)]=[40,80], height =40=40. Intersection =30×40=1200=30\times40=1200. Areas: A=(6010)(8020)=50×60=3000A=(60-10)(80-20)=50\times60=3000; B=(9030)(10040)=60×60=3600B=(90-30)(100-40)=60\times60=3600. Union =3000+36001200=5400=3000+3600-1200=5400. IoU=12005400=290.222.\text{IoU}=\frac{1200}{5400}=\frac{2}{9}\approx\mathbf{0.222}.

(b) (6 marks, 2 per axis + choice.) (i) YOLO: no separate proposal stage—dense grid cells directly regress boxes+class. R-CNN: a Region Proposal Network / selective search generates candidate ROIs, then a classifier refines them. (ii) YOLO is faster (single forward pass, real-time) but historically lower localization accuracy on small/overlapping objects; two-stage R-CNN is slower but more accurate. (iii) YOLO uses multiple anchors/bounding-box predictors per cell; R-CNN handles many objects via many proposals + per-ROI classification (NMS to dedup). Choice: YOLO (or SSD) for the 30 FPS drone — single-shot meets the real-time/compute budget of embedded hardware.

(c) (4 marks.) Skip connections copy high-resolution feature maps from the contracting path and concatenate them onto the upsampled decoder features, restoring fine spatial detail lost during pooling and giving the decoder both semantic (deep) and localization (shallow) information. Concatenation preserves both feature sets as separate channels for the next conv to combine, whereas ResNet addition fuses them into one tensor (requires matching channel count, learns a residual). Elastic deformation matters because biomedical datasets are small and cells/tissue vary in shape; realistic deformations teach invariance and expand effective training data.

(d) (3 marks.) Dice=2PGP+G\text{Dice}=\dfrac{2|P\cap G|}{|P|+|G|} (soft: 2pigipi+gi\frac{2\sum p_i g_i}{\sum p_i+\sum g_i}). Preferred because it directly measures foreground overlap and is insensitive to the vast correct-background majority, so it does not get inflated by class imbalance the way pixel accuracy does.

[
 {"claim":"L4 output spatial size is 56","code":"def O(I,P,k,s,d):\n keff=d*(k-1)+1\n return (I+2*P-keff)//s+1\nL1=O(224,3,7,2,1); L2=O(L1,1,3,2,1); L3=O(L2,2,3,1,2); L4=O(L3,1,3,1,1)\nresult = (L1==112 and L