Skip to content
ml-recall

Topic notes

Neural Network Basics

Neurons, perceptrons and MLPs; activation functions, output layers and losses, parameter counts, and how backpropagation computes gradients with the chain rule.

5-min read AI-checked

Practise 197 questions Take a test

Key ideas

Activation Formula Range Derivative
sigmoid σ(z)=1/(1+e−z)\sigma(z) = 1/(1 + e^{-z}) (0,1)(0, 1) σ(1−σ)\sigma(1 - \sigma), at most 0.25 (at 0)
tanh 2σ(2z)−12\sigma(2z) - 1 (−1,1)(-1, 1) 1−tanh⁡2z1 - \tanh^2 z, at most 1 (at 0)
ReLU max⁡(0,z)\max(0, z) [0,∞)[0, \infty) 0 if z<0z < 0, 1 if z>0z > 0
leaky ReLU / PReLU max⁡(0,z)+αmin⁡(0,z)\max(0, z) + \alpha\min(0, z) all reals (α>0\alpha > 0) 1 if z>0z > 0, α\alpha if z<0z < 0; ∂a/∂α=min⁡(0,z)\partial a/\partial\alpha = \min(0, z)
GELU / SiLU (Swish) z Φ(z)z\,\Phi(z) / z σ(z)z\,\sigma(z) dips slightly below 0 (GELU to about −0.17-0.17) smooth, not monotonic
Target Output Loss
real number identity MSE (predicts the conditional mean) or MAE (median)
one binary label sigmoid binary cross-entropy (log loss)
one of KK exclusive classes softmax categorical cross-entropy
several independent yes/no labels KK sigmoids sum of binary cross-entropies

Formulas

Dense layer on a minibatch in the row convention: Z=AW+bZ = AW + \mathbf{b} with input A∈RB×ninA \in \mathbb{R}^{B \times n_{\text{in}}} (A=XA = X for the first layer), WijW_{ij} the weight from input ii to unit jj, the bias row broadcast to every example, and upstream gradient D=∂L/∂ZD = \partial L/\partial Z:

∂L∂W=A⊤D,∂L∂b=∑nDn,:,∂L∂A=D W⊤,#params=nin nout+nout\frac{\partial L}{\partial W} = A^\top D,\qquad \frac{\partial L}{\partial \mathbf{b}} = \sum_n D_{n,:},\qquad \frac{\partial L}{\partial A} = D\,W^\top,\qquad \#\text{params} = n_{\text{in}}\,n_{\text{out}} + n_{\text{out}}

These are the column-convention rules for z=Wx+b\mathbf{z} = W\mathbf{x} + \mathbf{b}, namely δ x⊤\boldsymbol\delta\,\mathbf{x}^\top for the weights and W⊤δW^\top\boldsymbol\delta for the input7, transposed and summed over the batch; for a mean loss the 1/B1/B is already inside DD. The count does not depend on the batch size: a 3–5–2 net has (15+5)+(10+2)=32(15 + 5) + (10 + 2) = 32 parameters.

Through an activation, δ=∂L∂a⊙ϕ′(z)\boldsymbol\delta = \frac{\partial L}{\partial \mathbf{a}} \odot \phi'(\mathbf{z})7. Softmax with cross-entropy (ℓCE\ell_{\text{CE}} below, in its log-sum-exp form) gives the logit gradient pj−yjp_j - y_j8: the components sum to 0 and only the true class's is negative. Binary cross-entropy with a sigmoid gives p−yp - y; half-squared error 12(p−y)2\tfrac12(p - y)^2 with a sigmoid gives (p−y) p(1−p)(p - y)\,p(1 - p), which vanishes when the unit saturates, and with an identity output simply y^−y\hat y - y.

ℓCE=−∑jyjlog⁡pj=log⁡∑jezj−ztrue,ℓBCE=−ylog⁡p−(1−y)log⁡(1−p)\ell_{\text{CE}} = -\sum_j y_j \log p_j = \log\sum_j e^{z_j} - z_{\text{true}},\qquad \ell_{\text{BCE}} = -y\log p - (1 - y)\log(1 - p)

Gradient checking: by Taylor expansion the central difference [L(θ+ε)−L(θ−ε)]/(2ε)[L(\theta + \varepsilon) - L(\theta - \varepsilon)]/(2\varepsilon) has error O(ε2)O(\varepsilon^2), the forward difference [L(θ+ε)−L(θ)]/ε[L(\theta + \varepsilon) - L(\theta)]/\varepsilon only O(ε)O(\varepsilon).

Worked example

A 2–2–1 network in the row convention, z1=xW1+b1\mathbf{z}^1 = \mathbf{x}W^1 + \mathbf{b}^1, a1=ReLU(z1)\mathbf{a}^1 = \mathrm{ReLU}(\mathbf{z}^1), y^=a1v+c\hat y = \mathbf{a}^1\mathbf{v} + c, with x=[2,1]\mathbf{x} = [2, 1], W1=[1−1−12]W^1 = \begin{bmatrix} 1 & -1 \\ -1 & 2 \end{bmatrix} (row ii = weights from input ii), b1=[0,−1]\mathbf{b}^1 = [0, -1], v=[2,1]⊤\mathbf{v} = [2, 1]^\top, c=0.5c = 0.5, target y=1y = 1 and L=12(y^−y)2L = \tfrac12(\hat y - y)^2.

In code

import torch
import torch.nn.functional as F
z = torch.tensor([[2.0, 1.0, 0.0]], requires_grad=True)  # logits, true class 0
loss = F.cross_entropy(z, torch.tensor([0]))
loss.backward()
print(round(loss.item(), 4))           # 0.4076
print(torch.softmax(z, 1).detach())    # tensor([[0.6652, 0.2447, 0.0900]])
print(z.grad)                          # tensor([[-0.3348,  0.2447,  0.0900]]) = p - y
x = torch.tensor([-2.0, 0.0, 3.0], requires_grad=True)
torch.relu(x).sum().backward()
print(x.grad)                          # tensor([0., 0., 1.])  slope 0 at exactly 0
bce = F.binary_cross_entropy_with_logits(torch.tensor([2.0]), torch.tensor([0.0]))
print(round(bce.item(), 4))            # 2.1269 = -log(1 - sigmoid(2))

Common pitfalls

References

  1. Wikipedia: Perceptron — Learning algorithm for a single-layer perceptron (Steps; Convergence of one perceptron on a linearly separable dataset); History, Perceptrons (1969)
  2. Dive into Deep Learning — Sec. 5.1 Multilayer Perceptrons (5.1.1.2 Incorporating Hidden Layers, 5.1.1.3 From Linear to Nonlinear, 5.1.1.4 Universal Approximators, 5.1.2 Activation Functions)
  3. Wikipedia: Universal approximation theorem — Introduction; Arbitrary-width case
  4. Telgarsky (2016), Benefits of depth in neural networks — Sec. 3.3 Many layers, many oscillations (Lemmas 3.10–3.11, the ReLU triangle map)
  5. Hendrycks & Gimpel (2016), Gaussian Error Linear Units (GELUs) — Sec. 2 GELU Formulation (GELU and SiLU); Sec. 4 Discussion
  6. PyTorch documentation: torch.nn.CrossEntropyLoss — CrossEntropyLoss (input is unnormalized logits; equivalent to LogSoftmax followed by NLLLoss)
  7. Dive into Deep Learning — Sec. 5.3.3 Backpropagation (Eqs. 5.3.11–5.3.14), 5.3.4 Training Neural Networks
  8. Dive into Deep Learning — Sec. 4.1.2.2 Softmax and Cross-Entropy Loss (Eqs. 4.1.9–4.1.10)