% ============================================================================ % Artificial Neural Networks — Methods, Equations and Graphical % Representations % Author : Simon-Pierre Boucher — contact@spboucher.ai % Chapter 4 : Convolutional Neural Networks (chapters/04-cnn.tex) % ============================================================================ \chapter{Convolutional Neural Networks}\label{chap:cnn} Fully connected networks treat every input coordinate as unrelated to every other: a pixel in the top-left corner of an image and its immediate neighbour are, as far as the architecture is concerned, as distant as two arbitrary pixels. Convolutional neural networks (CNNs) build the spatial structure of the data directly into the architecture through three mechanisms: \emph{local connectivity} (each unit sees only a small window of the input), \emph{weight sharing} (the same filter is applied at every position, so a feature detector learned in one place is available everywhere), and \emph{hierarchical composition} (stacked layers assemble edges into textures, textures into parts, parts into objects). This chapter develops the convolution and pooling operations, assembles them into the canonical convolutional architecture of LeCun et al.~\cite{lecun1998}, analyses the residual connection of He et al.~\cite{he2016} that made very deep networks trainable, and closes with the notion of receptive field and a brief genealogy of modern architectures. % ---------------------------------------------------------------------------- \section{From the Visual Cortex to the Convolutional Layer} The lineage of the CNN begins in neurophysiology. Recording from the cat's visual cortex, Hubel and Wiesel identified \emph{simple cells}, which respond to oriented edges at specific retinal positions, and \emph{complex cells}, which respond to the same features with tolerance to small shifts. Fukushima's \emph{Neocognitron} (1980) translated this two-cell hierarchy into a network that alternates feature-extracting S-cells — local receptive fields with shared weights, the conceptual ancestor of the convolutional layer — with position-tolerant C-cells, the ancestor of pooling. What the Neocognitron lacked was end-to-end supervised training: that ingredient was supplied when backpropagation was applied to weight-shared architectures, culminating in LeNet-5~\cite{lecun1998}, the first widely deployed CNN, which read millions of bank cheques using the canonical pattern $[\text{conv} \to \text{pool}] \times N \to \text{dense} \to \text{output}$ that this chapter formalizes. % ---------------------------------------------------------------------------- \section{The Convolution Operation} \subsection{Definition} \begin{definition}[Discrete two-dimensional convolution]\label{def:cnn-conv} Let $I$ be an input map and $K \in \R^{k_h \times k_w}$ a kernel (filter). The discrete convolution of $I$ by $K$ is \begin{equation}\label{eq:cnn-conv2d} S(i,j) \;=\; (I * K)(i,j) \;=\; \sum_{m=0}^{k_h-1} \sum_{n=0}^{k_w-1} I(i-m,\, j-n)\, K(m,n). \end{equation} \end{definition} \begin{remark}[Convolution versus cross-correlation]\label{rem:cnn-crosscorr} Deep learning frameworks implement \emph{cross-correlation} — the same sum without flipping the kernel, i.e.\ with indices $I(i+m,\,j+n)$. Since the kernel entries are learned, the two operations are equivalent up to a re-parameterization of the weights, and the term ``convolution'' is used for both. All equations below follow the cross-correlation convention. \end{remark} In a convolutional \emph{layer}, the input is a stack of $C_{\mathrm{in}}$ channels $\vect{x} \in \R^{C_{\mathrm{in}} \times H \times W}$, and each of the $C_{\mathrm{out}}$ output channels is produced by its own three-dimensional filter plus a bias. With stride $s$ and zero-padding $p$ (writing $\tilde{\vect{x}}$ for the input bordered by $p$ zeros on each side), the output channel $c_{\mathrm{out}}$ is \begin{equation}\label{eq:cnn-convlayer} y_{c_{\mathrm{out}}}(i,j) \;=\; b_{c_{\mathrm{out}}} \;+\; \sum_{c=1}^{C_{\mathrm{in}}} \sum_{m=0}^{k_h-1} \sum_{n=0}^{k_w-1} W_{c_{\mathrm{out}},c}(m,n)\; \tilde{x}_{c}\big(s\,i + m,\; s\,j + n\big), \end{equation} where $i,j$ index the output positions. Three properties of \eqref{eq:cnn-convlayer} explain the effectiveness of the operation. Each output value depends only on a $k_h \times k_w$ window of the input (\emph{local connectivity}); the same weights $W_{c_{\mathrm{out}},c}$ are used at every position $(i,j)$ (\emph{weight sharing}), which makes the layer \emph{equivariant} to translation — a shifted input produces a correspondingly shifted output — and reduces the parameter count dramatically; and stacking such layers composes local detectors into progressively more global and abstract ones~\cite{goodfellow2016book}. Algorithm~\ref{alg:cnn-forward} spells out the layer's forward pass as literal loops over \eqref{eq:cnn-convlayer} — production implementations replace the loops with im2col-plus-GEMM or FFT-based routines, but compute exactly the same map. \begin{algorithm}[htbp] \caption{Forward pass of a convolutional layer (stride $s$, padding $p$)} \label{alg:cnn-forward} \begin{algorithmic}[1] \Require input $\vect{x} \in \R^{C_{\mathrm{in}} \times H \times W}$, weights $W \in \R^{C_{\mathrm{out}} \times C_{\mathrm{in}} \times k_h \times k_w}$, biases $\vect{b}$, activation $\varphi$ \State $\tilde{\vect{x}} \gets$ zero-pad $\vect{x}$ with a border of $p$ zeros on each spatial side \State $H_{\mathrm{out}} \gets \lfloor (H + 2p - k_h)/s \rfloor + 1$; \quad $W_{\mathrm{out}} \gets \lfloor (W + 2p - k_w)/s \rfloor + 1$ \Comment{\eqref{eq:cnn-outsize}} \For{$c_{\mathrm{out}} = 1, \dots, C_{\mathrm{out}}$} \For{$i = 0, \dots, H_{\mathrm{out}}-1$;\; $j = 0, \dots, W_{\mathrm{out}}-1$} \State $u \gets b_{c_{\mathrm{out}}}$ \For{$c = 1, \dots, C_{\mathrm{in}}$;\; $m = 0, \dots, k_h - 1$;\; $n = 0, \dots, k_w - 1$} \State $u \gets u + W_{c_{\mathrm{out}},c}(m,n)\, \tilde{x}_c(s\,i + m,\; s\,j + n)$ \Comment{windowed sum \eqref{eq:cnn-convlayer}} \EndFor \State $y_{c_{\mathrm{out}}}(i,j) \gets \varphi(u)$ \EndFor \EndFor \State \Return $\vect{y} \in \R^{C_{\mathrm{out}} \times H_{\mathrm{out}} \times W_{\mathrm{out}}}$ \end{algorithmic} \end{algorithm} \subsection{Stride, Padding and Output Geometry} The \emph{stride} $s$ is the step of the sliding window: $s>1$ downsamples the output. The \emph{padding} $p$ adds a border of zeros; ``valid'' convolution uses $p=0$, while ``same'' padding, $p = \lfloor k/2 \rfloor$ for odd $k$ and $s=1$, preserves the spatial size. For an input of height $H$, kernel size $k$, padding $p$ and stride $s$, the output height is \begin{equation}\label{eq:cnn-outsize} H_{\mathrm{out}} \;=\; \left\lfloor \frac{H + 2p - k}{s} \right\rfloor + 1, \end{equation} and symmetrically for the width. (With \emph{dilation} $d$, which inserts $d-1$ gaps between kernel taps, $k$ in \eqref{eq:cnn-outsize} is replaced by the effective size $k_{\mathrm{eff}} = d(k-1)+1$; dilation enlarges receptive fields without adding parameters.) Figure~\ref{fig:cnn-grid} traces \eqref{eq:cnn-convlayer} on a concrete example: a $5 \times 5$ input, a $3 \times 3$ vertical-edge kernel, stride $s=1$ and padding $p=0$, so that \eqref{eq:cnn-outsize} gives $H_{\mathrm{out}} = \lfloor (5 + 0 - 3)/1 \rfloor + 1 = 3$. \begin{figure}[t] \centering \begin{tikzpicture} % -------- input grid 5x5 (6 mm cells), top-left corner at (0,0) \fill[cinput!30] (0,0) rectangle (1.8,-1.8); \draw[black!60] (0,-3) grid[step=6mm] (3,0); \draw[cinput!80!black, very thick] (0,0) rectangle (1.8,-1.8); \foreach \v [count=\k from 0] in {1,2,0,1,3, 0,1,2,3,1, 1,0,2,2,0, 2,1,0,1,2, 0,2,1,0,1}{ \pgfmathtruncatemacro{\r}{int(\k/5)} \pgfmathtruncatemacro{\c}{mod(\k,5)} \node[font=\small] at (\c*0.6+0.3, -\r*0.6-0.3) {$\v$}; } \node[etiquette, font=\small] at (1.5,-3.45) {input $5\times5$}; % -------- operator \node[font=\large] at (3.9,-1.5) {$\ast$}; % -------- kernel 3x3, vertically centred on the input \begin{scope}[shift={(4.8,-0.6)}] \fill[cgate!15] (0,0) rectangle (1.8,-1.8); \draw[black!60] (0,-1.8) grid[step=6mm] (1.8,0); \foreach \v [count=\k from 0] in {1,0,-1, 1,0,-1, 1,0,-1}{ \pgfmathtruncatemacro{\r}{int(\k/3)} \pgfmathtruncatemacro{\c}{mod(\k,3)} \node[font=\small] at (\c*0.6+0.3, -\r*0.6-0.3) {$\v$}; } \node[etiquette, font=\small] at (0.9,-2.25) {kernel $3\times3$}; \end{scope} % -------- operator \node[font=\large] at (7.2,-1.5) {$=$}; % -------- output grid 3x3 \begin{scope}[shift={(7.8,-0.6)}] \fill[coutput!30] (0,0) rectangle (0.6,-0.6); \draw[black!60] (0,-1.8) grid[step=6mm] (1.8,0); \draw[coutput!80!black, very thick] (0,0) rectangle (0.6,-0.6); \foreach \v [count=\k from 0] in {-2,-3,0, -1,-4,1, 0,0,0}{ \pgfmathtruncatemacro{\r}{int(\k/3)} \pgfmathtruncatemacro{\c}{mod(\k,3)} \node[font=\small] at (\c*0.6+0.3, -\r*0.6-0.3) {$\v$}; } \node[etiquette, font=\small] at (0.9,-2.25) {output $3\times3$}; \end{scope} % -------- window -> output cell \draw[flechep, cinput!80!black] (0.9,0.12) to[bend left=18] (8.1,-0.5); \end{tikzpicture} \caption{Convolution (cross-correlation) of a $5\times5$ input with a $3\times3$ vertical-edge kernel, stride $s=1$, padding $p=0$. The highlighted window produces the highlighted output cell: $1\cdot1 + 2\cdot0 + 0\cdot(-1) + 0\cdot1 + 1\cdot0 + 2\cdot(-1) + 1\cdot1 + 0\cdot0 + 2\cdot(-1) = -2$. Sliding the window over all nine valid positions fills the $3\times3$ output map, in accordance with \eqref{eq:cnn-outsize}.} \label{fig:cnn-grid} \end{figure} \subsection{Parameter Efficiency} The number of parameters of the layer \eqref{eq:cnn-convlayer} is \begin{equation}\label{eq:cnn-params} \#\text{params} \;=\; C_{\mathrm{out}} \left( C_{\mathrm{in}}\, k_h\, k_w + 1 \right), \end{equation} \emph{independent of the spatial resolution} $H \times W$ — the decisive advantage over a dense layer, whose parameter count grows with the square of the image size. A $3\times3$ convolution mapping $64$ channels to $64$ channels costs $36{,}928$ parameters whether the image is $32\times32$ or $1024\times1024$. % ---------------------------------------------------------------------------- \section{Pooling} Pooling summarizes each local neighbourhood of a feature map by a single value, providing a small amount of translation \emph{invariance} (on top of the equivariance of convolution) and reducing the spatial resolution. Let $\mathcal{R}_{ij}$ denote the $k \times k$ window of input positions associated with output position $(i,j)$ (with stride $s$, typically $k=s=2$). \emph{Max pooling} keeps the strongest activation, \begin{equation}\label{eq:cnn-maxpool} y_c(i,j) \;=\; \max_{(m,n)\,\in\,\mathcal{R}_{ij}} x_c(m,n), \end{equation} whereas \emph{average pooling} keeps the mean response, \begin{equation}\label{eq:cnn-avgpool} y_c(i,j) \;=\; \frac{1}{\lvert \mathcal{R}_{ij} \rvert} \sum_{(m,n)\,\in\,\mathcal{R}_{ij}} x_c(m,n). \end{equation} The limiting case of \eqref{eq:cnn-avgpool}, \emph{global average pooling}, collapses each channel's entire $H \times W$ map to one scalar, \begin{equation}\label{eq:cnn-gap} y_c \;=\; \frac{1}{HW} \sum_{i=1}^{H} \sum_{j=1}^{W} x_c(i,j), \end{equation} and is the modern replacement for the large dense layers that dominated the parameter budget of early CNNs: it contributes no parameters, acts as a structural regularizer, and lets the same network accept inputs of any size. % ---------------------------------------------------------------------------- \section{The Canonical Convolutional Architecture} Assembling the two operations yields the canonical architecture of Figure~\ref{fig:cnn-archi}: a \emph{feature-extraction} stage alternating convolution (+ nonlinearity) and pooling, in which the spatial resolution decreases while the channel count — the richness of the learned vocabulary — increases; then a \emph{classification} stage, in which the final maps are flattened (or globally pooled) into a vector, passed through dense layers, and mapped by a softmax to class probabilities. This is exactly the structure of LeNet-5~\cite{lecun1998}, which stacked two conv--pool pairs and two dense layers ($\sim$60k parameters) and established that such a pipeline can be trained end to end by gradient descent on raw pixels. \begin{figure}[t] \centering \begin{tikzpicture}[node distance=0.55cm] \node[blocinput, minimum width=1.05cm, minimum height=2.6cm, font=\scriptsize] (in) {input\\image}; \node[blochidden, minimum width=1.05cm, minimum height=2.6cm, font=\scriptsize, right=of in] (c1) {conv\\ReLU}; \node[bloc, minimum width=0.95cm, minimum height=2.0cm, font=\scriptsize, right=of c1] (p1) {pool}; \node[blochidden, minimum width=1.05cm, minimum height=2.0cm, font=\scriptsize, right=of p1] (c2) {conv\\ReLU}; \node[bloc, minimum width=0.95cm, minimum height=1.4cm, font=\scriptsize, right=of c2] (p2) {pool}; \node[bloc, minimum width=1.0cm, minimum height=2.2cm, font=\scriptsize, right=of p2] (fl) {flatten}; \node[blochidden, minimum width=1.0cm, minimum height=1.7cm, font=\scriptsize, right=of fl] (fc) {dense\\ReLU}; \node[blocoutput, minimum width=1.1cm, minimum height=1.2cm, font=\scriptsize, right=of fc] (sm) {softmax}; \foreach \a/\b in {in/c1, c1/p1, p1/c2, c2/p2, p2/fl, fl/fc, fc/sm} \draw[fleche] (\a) -- (\b); % grouping braces \draw[decorate, decoration={brace, mirror, amplitude=5pt}] (c1.west |- 0,-1.55) -- (p2.east |- 0,-1.55) node[midway, below=7pt, etiquette, font=\small]{feature extraction}; \draw[decorate, decoration={brace, mirror, amplitude=5pt}] (fl.west |- 0,-1.55) -- (sm.east |- 0,-1.55) node[midway, below=7pt, etiquette, font=\small]{classification}; \end{tikzpicture} \caption{The canonical convolutional architecture in the lineage of LeNet-5~\cite{lecun1998}. In the feature-extraction stage the spatial resolution shrinks (decreasing block heights) while the channel count grows; the classification stage flattens the final maps and applies dense layers followed by a softmax.} \label{fig:cnn-archi} \end{figure} The historical turning point came when this recipe met large datasets and GPU computing: AlexNet's 2012 ImageNet victory — five convolutional and three dense layers, ReLU activations and dropout — cut the top-5 error from 26.2\% to 15.3\% and opened the modern era of deep learning~\cite{goodfellow2016book}. % ---------------------------------------------------------------------------- \section{Residual Learning} Depth is the currency of representational power, yet naively stacking layers eventually makes even the \emph{training} error worse — the \emph{degradation problem}. A network of $50$ plain layers underperforms its $20$-layer counterpart not because of overfitting but because the optimizer fails to find a solution as good as ``the shallow network plus identity layers'', although one exists by construction. Residual learning~\cite{he2016} removes this obstacle by making the identity the default behaviour of every block: instead of asking a block to learn a mapping $\mathcal{H}(\vect{x})$ directly, one asks it to learn only the \emph{residual} $\mathcal{F}(\vect{x}) = \mathcal{H}(\vect{x}) - \vect{x}$ and adds the input back through a shortcut connection, \begin{equation}\label{eq:cnn-residual} \vect{y} \;=\; \mathcal{F}(\vect{x}, \{\mat{W}_i\}) + \vect{x}, \end{equation} where typically $\mathcal{F}$ consists of two convolution--batch-norm stages with a ReLU in between (Figure~\ref{fig:cnn-resblock}), and a learned projection $\mat{W}_s \vect{x}$ replaces the identity when dimensions change. If the optimal mapping is close to the identity, the block merely needs to drive $\mathcal{F}$ towards zero — far easier than reproducing the identity through a stack of nonlinear layers. \begin{figure}[t] \centering \begin{tikzpicture} \node (xl) at (0,0) {$\vect{x}$}; \node[blochidden, right=0.95cm of xl, minimum width=2.3cm] (f1) {conv $3{\times}3$\\BN, ReLU}; \node[blochidden, right=0.7cm of f1, minimum width=2.3cm] (f2) {conv $3{\times}3$\\BN}; \node[op, right=0.95cm of f2] (plus) {$+$}; \node[bloc, right=0.7cm of plus, minimum width=1.1cm] (relu) {ReLU}; \node[right=0.7cm of relu] (y) {$\vect{y}$}; \draw[fleche] (xl) -- (f1); \draw[fleche] (f1) -- (f2); \draw[fleche] (f2) -- (plus); \draw[fleche] (plus) -- (relu); \draw[fleche] (relu) -- (y); % identity shortcut \coordinate (tap) at ($(xl.east)+(0.45,0)$); \fill (tap) circle (1.3pt); \draw[fleche, cmem!80!black] (tap) -- ++(0,1.35) -| (plus.north); \node[etiquette, font=\small, text=cmem!80!black] at ($(f1.north)!0.5!(f2.north)+(0,1.15)$) {identity shortcut $\vect{x}$}; \node[etiquette, font=\small] at ($(f1.south)!0.5!(f2.south)+(0,-0.35)$) {residual branch $\mathcal{F}(\vect{x})$}; \end{tikzpicture} \caption{The residual block of ResNet~\cite{he2016}. The main path computes the residual $\mathcal{F}(\vect{x})$ through two convolution--batch-norm stages; the shortcut carries $\vect{x}$ unchanged to the addition node, implementing \eqref{eq:cnn-residual}.} \label{fig:cnn-resblock} \end{figure} \begin{property}[Gradient flow through the identity shortcut]\label{prop:cnn-resgrad} Consider a stack of residual blocks $\vect{x}_{\ell+1} = \vect{x}_\ell + \mathcal{F}(\vect{x}_\ell)$. Unrolling from layer $\ell$ to any deeper layer $L$ gives \begin{equation}\label{eq:cnn-unroll} \vect{x}_L \;=\; \vect{x}_\ell \;+\; \sum_{i=\ell}^{L-1} \mathcal{F}(\vect{x}_i), \end{equation} and the chain rule then yields \begin{equation}\label{eq:cnn-resgrad} \frac{\partial \Loss}{\partial \vect{x}_\ell} \;=\; \frac{\partial \Loss}{\partial \vect{x}_L} \left( \mat{I} \;+\; \frac{\partial}{\partial \vect{x}_\ell} \sum_{i=\ell}^{L-1} \mathcal{F}(\vect{x}_i) \right). \end{equation} The additive identity term $\mat{I}$ in \eqref{eq:cnn-resgrad} provides a direct gradient path from any layer to any shallower layer: the gradient cannot vanish even when the Jacobian of the residual branch is small, because it is never forced through a long product of weight matrices. \end{property} This single architectural idea allowed networks of $152$ layers — eight times deeper than the deepest previous mainstream design yet cheaper in floating-point operations — to win the 2015 ImageNet competition with a 3.57\% top-5 ensemble error~\cite{he2016}; the same shortcut structure reappears in virtually every subsequent deep architecture, including the Transformer. % ---------------------------------------------------------------------------- \section{The Receptive Field} The \emph{receptive field} of a unit is the region of the input image that can influence its value. For a stack of layers where layer $\ell$ has kernel size $k_\ell$ and stride $s_\ell$, the receptive field $r_\ell$ grows according to the recursion \begin{equation}\label{eq:cnn-receptive} r_\ell \;=\; r_{\ell-1} \;+\; (k_\ell - 1) \prod_{i=1}^{\ell-1} s_i, \qquad r_0 = 1, \end{equation} where the product accounts for the cumulative downsampling in front of layer $\ell$. Two consequences guide architecture design. First, small kernels compose efficiently: two stacked $3\times3$ convolutions reach the same $5\times5$ receptive field as one $5\times5$ kernel with fewer parameters ($18C^2$ versus $25C^2$) and one extra nonlinearity — the observation that underlies VGG's uniform $3\times3$ design. Second, strides and pooling are multiplicative in \eqref{eq:cnn-receptive}: early downsampling is the cheapest way to grow the receptive field, which is why deep units eventually see the whole image and can encode global, object-level structure. % ---------------------------------------------------------------------------- \section{A Brief Genealogy of Architectures} Table~\ref{tab:cnn-genealogy} summarizes the milestones that separate LeNet-5 from today's networks. Beyond ResNet, three ideas deserve mention. \emph{Multi-branch design} (GoogLeNet's Inception module) processes each position at several kernel sizes in parallel and concatenates the results, using $1\times1$ ``bottleneck'' convolutions to keep the cost low — 22 layers with only $\sim$7M parameters. \emph{Dense connectivity} (DenseNet) generalizes the shortcut of \eqref{eq:cnn-residual} by concatenating, rather than adding, the features of \emph{all} preceding layers, maximizing feature reuse and gradient flow. \emph{Factorized convolution} (MobileNet) splits a standard convolution into a per-channel (depthwise) spatial filter followed by a $1\times1$ (pointwise) channel mixer; on a feature map with $M$ input channels, $N$ output channels and a $D_K \times D_K$ kernel, the cost ratio relative to the standard layer is \begin{equation}\label{eq:cnn-separable} \frac{\text{separable}}{\text{standard}} \;=\; \frac{1}{N} + \frac{1}{D_K^2}, \end{equation} about an $8$--$9\times$ saving for $3\times3$ kernels — the enabling arithmetic of mobile and embedded vision. \begin{table}[t] \centering \caption{Milestones of convolutional architecture design.} \label{tab:cnn-genealogy} \begin{tabular}{@{}llll@{}} \toprule Year & Architecture & Key idea & Scale \\ \midrule 1980 & Neocognitron & S/C-cell hierarchy, weight sharing & --- \\ 1998 & LeNet-5~\cite{lecun1998} & end-to-end conv--pool--dense & 60k \\ 2012 & AlexNet & ReLU, dropout, GPU training & 60M \\ 2014 & VGG & uniform $3\times3$ depth & 138M \\ 2014 & GoogLeNet & Inception multi-branch, $1\times1$ bottlenecks & 7M \\ 2015 & ResNet~\cite{he2016} & identity shortcut \eqref{eq:cnn-residual} & 25M \\ 2017 & DenseNet & concatenated dense connectivity & 8M \\ 2017 & MobileNet & depthwise separable conv.\ \eqref{eq:cnn-separable} & 4M \\ 2019 & EfficientNet & compound depth/width/resolution scaling & 5--66M \\ 2022 & ConvNeXt & modernized ResNet, $7\times7$ depthwise & 29M+ \\ \bottomrule \end{tabular} \end{table} The through-line of this genealogy is that every leap either improved \emph{gradient flow} (ReLU, batch normalization, the shortcut of \eqref{eq:cnn-resgrad}) or improved the \emph{allocation of computation} (bottlenecks, separable filters, compound scaling). The convolutional prior itself — locality, weight sharing, hierarchy — has remained intact from the Neocognitron to ConvNeXt, and it transfers beyond images: 1D convolutions over sequences and 3D convolutions over videos and volumes are the direct analogues of \eqref{eq:cnn-convlayer} with one fewer or one more spatial index~\cite{goodfellow2016book}.