Level 3 — ProductionConvolutional Neural Networks

Convolutional Neural Networks

45 minutes60 marksprintable — key stays hidden on paper

Level 3 — Production (from-scratch derivations, code-from-memory, explain-out-loud) Time limit: 45 minutes Total marks: 60

Instructions: Answer all questions. Show every derivation step. Where code is requested, write it from memory (minor syntax slips are tolerated if logic is correct). Use ...... for math.


Question 1 — Output shape & parameter derivation (10 marks)

A convolutional layer receives an input tensor of shape H×W×Cin=224×224×3H \times W \times C_{in} = 224 \times 224 \times 3.

(a) Derive the general formula for the spatial output dimension of a convolution with kernel size KK, padding PP, stride SS, and dilation DD. (3)

(b) Using your formula, compute the output height for K=7K=7, P=3P=3, S=2S=2, D=1D=1. (2)

(c) The layer has 6464 filters. Compute the total number of learnable parameters (with bias). (2)

(d) Compute the number of multiply–accumulate (MAC) operations for producing the full output tensor. (3)


Question 2 — Receptive field derivation (10 marks)

Consider a stack of three 3×33\times3 convolutions, each with stride 1, no dilation.

(a) Derive from scratch the recurrence for the receptive field rr_\ell at layer \ell in terms of r1r_{\ell-1}, kernel size kk_\ell, and the cumulative stride (jump) j1j_{\ell-1}. (4)

(b) Compute the receptive field after the three 3×33\times3 layers. (2)

(c) Explain out loud (in words) why VGG replaces a single 7×77\times7 conv with three stacked 3×33\times3 convs — address both receptive field and parameter count. (4)


Question 3 — Code from memory: 2D convolution (12 marks)

(a) Write a NumPy function conv2d(x, w, stride, pad) that performs a valid single-channel 2D cross-correlation with zero padding. Assume x is (H,W) and w is (kH,kW). (8)

(b) State the shape of the output and explain what happens numerically if you forget to flip the kernel (cross-correlation vs. true convolution). (4)


Question 4 — ResNet residual block (out-loud + derivation) (12 marks)

(a) Draw/describe the structure of a basic ResNet residual block, writing the output equation y=F(x,{Wi})+xy = \mathcal{F}(x, \{W_i\}) + x. (3)

(b) Derive the gradient Lx\frac{\partial \mathcal{L}}{\partial x} through the block and explain out loud why the skip connection mitigates vanishing gradients. (5)

(c) When the number of channels changes across a block, the identity path cannot be added directly. Explain the two standard fixes and their parameter trade-off. (4)


Question 5 — Architecture reasoning (8 marks)

(a) Explain the purpose of the 1×11\times1 convolution in the Inception module and compute the parameter saving of a 1×11\times1 (32 filters) bottleneck placed before a 5×55\times5 (64 filters) conv, given a 28×28×19228\times28\times192 input, versus applying the 5×55\times5 directly. (6)

(b) State one architectural idea each that DenseNet and EfficientNet contribute. (2)


Question 6 — Transfer learning & pipeline (8 marks)

(a) You have 2,000 labelled medical images and a model pretrained on ImageNet. Describe an out-loud strategy: which layers to freeze, learning rate choice, and why. (4)

(b) List four data augmentation transforms suitable for natural-image classification and one that would be inappropriate for digit (e.g. MNIST) recognition, justifying the exclusion. (4)


Answer keyMark scheme & solutions

Question 1 (10 marks)

(a) With dilation, the effective kernel size is Keff=D(K1)+1K_{eff} = D(K-1)+1. Sliding it across a padded input of length H+2PH+2P with stride SS: Hout=H+2PD(K1)1S+1H_{out} = \left\lfloor \frac{H + 2P - D(K-1) - 1}{S} \right\rfloor + 1

  • Effective kernel size (1)
  • Padding term & numerator (1)
  • Floor + 1 (1)

(b) Hout=(224+6161)/2+1=223/2+1=111+1=112H_{out} = \lfloor (224 + 6 - 1\cdot6 - 1)/2 \rfloor + 1 = \lfloor 223/2 \rfloor + 1 = 111 + 1 = 112. (2)

(c) Params =(KKCin+1)F=(773+1)64=(147+1)64=14864=9472= (K\cdot K \cdot C_{in} + 1)\cdot F = (7\cdot7\cdot3 + 1)\cdot 64 = (147+1)\cdot64 = 148\cdot64 = 9472. (2)

  • Correct weight count 7·7·3·64 (1), bias +64 (1)

(d) Output is 112×112×64112\times112\times64. Each output element = 773=1477\cdot7\cdot3 = 147 MACs. MACs=11211264147=802816147=118,013,9521.18×108.\text{MACs} = 112\cdot112\cdot64\cdot147 = 802816\cdot147 = 118{,}013{,}952 \approx 1.18\times10^8.

  • Output positions 112264112^2\cdot64 (1), MACs per output 147 (1), product (1)

Question 2 (10 marks)

(a) Cumulative jump: j=j1sj_\ell = j_{\ell-1}\cdot s_\ell, with j0=1j_0=1. Receptive field recurrence: r=r1+(k1)j1r_\ell = r_{\ell-1} + (k_\ell - 1)\cdot j_{\ell-1} with r0=1r_0 = 1. Reasoning: each new layer's kernel spans kk_\ell units, but each unit at the previous layer already covers j1j_{\ell-1} input pixels, so the extra (k1)(k_\ell-1) units add (k1)j1(k_\ell-1)j_{\ell-1}. (4)

(b) Stride 1 ⇒ j=1j=1 throughout. r1=1+21=3r_1 = 1 + 2\cdot1 = 3; r2=3+21=5r_2 = 3 + 2\cdot1 = 5; r3=5+21=7r_3 = 5 + 2\cdot1 = 7. RF = 7. (2)

(c) Three 3×33\times3 convs give the same 7×77\times7 receptive field. Parameter count: 3×(32C2)=27C23\times(3^2 C^2) = 27C^2 vs. 72C2=49C27^2 C^2 = 49C^2 — a ~45% reduction. Additionally, the stack inserts two extra non-linearities, increasing representational (decision-boundary) capacity. (4: RF equivalence 1, param comparison 2, non-linearity point 1)


Question 3 (12 marks)

(a) (8 marks: padding 2, output alloc 2, loops/window 2, correctness 2)

import numpy as np
 
def conv2d(x, w, stride=1, pad=0):
    if pad > 0:
        x = np.pad(x, ((pad, pad), (pad, pad)), mode='constant')
    H, W = x.shape
    kH, kW = w.shape
    oH = (H - kH) // stride + 1
    oW = (W - kW) // stride + 1
    out = np.zeros((oH, oW))
    for i in range(oH):
        for j in range(oW):
            r, c = i * stride, j * stride
            region = x[r:r+kH, c:c+kW]
            out[i, j] = np.sum(region * w)
    return out

(b) Output shape =(H+2PkHS+1, W+2PkWS+1)= \left(\frac{H+2P-kH}{S}+1,\ \frac{W+2P-kW}{S}+1\right). (2) Cross-correlation (no flip) is what deep-learning frameworks actually use; a true convolution flips the kernel both horizontally and vertically (w[::1,::1]w[::-1,::-1]). For a learned filter it makes no functional difference — the network just learns the mirrored weights — so omitting the flip is standard and correct in ML. (2)


Question 4 (12 marks)

(a) Block: conv3x3 → BN → ReLU → conv3x3 → BN, then add the input (identity), then final ReLU. Output: y=F(x,{Wi})+x.y = \mathcal{F}(x, \{W_i\}) + x. (3)

(b) Lx=Lyyx=Ly(Fx+I)\frac{\partial \mathcal{L}}{\partial x} = \frac{\partial \mathcal{L}}{\partial y}\cdot\frac{\partial y}{\partial x} = \frac{\partial \mathcal{L}}{\partial y}\left(\frac{\partial \mathcal{F}}{\partial x} + I\right). Out loud: because of the identity term II, the upstream gradient L/y\partial\mathcal{L}/\partial y flows directly to xx even if F/x0\partial\mathcal{F}/\partial x \to 0. The gradient never fully vanishes as depth grows — the "+I+I" guarantees a highway for gradient flow, enabling very deep networks (100+ layers) to train. (5: chain rule + I term 3, out-loud explanation 2)

(c) (1) Projection shortcut — a 1×11\times1 conv with stride on the identity path to match channels/spatial dims (adds parameters). (2) Zero-padding the identity's extra channels (parameter-free but less expressive). Trade-off: projection costs CinCoutC_{in}\cdot C_{out} params but preserves representational capacity; padding is free but adds no learning. (4)


Question 5 (8 marks)

(a) The 1×11\times1 conv is a channel-wise bottleneck: it reduces the depth cheaply before an expensive spatial conv, cutting computation/params.

Direct 5×55\times5: params =5519264=307,200= 5\cdot5\cdot192\cdot64 = 307{,}200. Bottleneck: 1×11\times1 (192→32): 1119232=6,1441\cdot1\cdot192\cdot32 = 6{,}144; then 5×55\times5 (32→64): 553264=51,2005\cdot5\cdot32\cdot64 = 51{,}200. Total =57,344= 57{,}344. Saving =307,20057,344=249,856= 307{,}200 - 57{,}344 = 249{,}856 params (≈81% reduction). (6: direct 2, bottleneck two terms 2, saving 2)

(b) DenseNet: dense connectivity — each layer receives feature maps of all preceding layers (concatenation) for feature reuse. EfficientNet: compound scaling — jointly scale depth, width, and resolution by a fixed ratio. (2)


Question 6 (8 marks)

(a) With only 2,000 images: freeze the early/mid convolutional layers (generic edge/texture features transfer well) and fine-tune only the later layers + new classifier head. Use a small learning rate (e.g. 10410^{-4}) so pretrained weights aren't destroyed; optionally a higher LR on the new head. Small dataset ⇒ heavy freezing prevents overfitting. (4)

(b) Suitable: random horizontal flip, random crop/scale, color jitter, rotation (small), random erasing. (any 4 → 2 marks) Inappropriate for MNIST digits: horizontal/vertical flip or large rotation — because they change semantic identity (a flipped/rotated "6" becomes a "9" or invalid glyph), corrupting labels. (2)


[
  {"claim":"Q1b output height = 112","code":"K,P,S,D=7,3,2,1; H=224; result=(( (H+2*P-D*(K-1)-1)//S)+1)==112"},
  {"claim":"Q1c params = 9472","code":"result=((7*7*3+1)*64)==9472"},
  {"claim":"Q1d MACs = 118013952","code":"result=(112*112*64*147)==118013952"},
  {"claim":"Q2b receptive field of three 3x3 = 7","code":"r=1\nfor _ in range(3): r=r+(3-1)*1\nresult=r==7"},
  {"claim":"Q5 bottleneck saving = 249856","code":"direct=5*5*192*64; bott=1*1*192*32+5*5*32*64; result=(direct-bott)==249856"}
]