Multilayer Perceptrons and Backpropagation › Formula

Michael BrenndoerferOctober 29, 202620 min read
Machine Learning from ScratchAll chapters
Part 7 of 15Supervised Learning Beyond Linear Models
Chapter 57Multilayer Perceptrons and Backpropagation › Formula
Reading section 4 of 10 · Formula · 20 minSection 4 of 10 · 20 min

Section 4 of 10 · 20 min read

Multilayer Perceptrons and Backpropagation › FormulaSection view · Sections in this chapter4 / 10 ↓
Reading tools Definitions, links & notes

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Notes & comments

With the motivation in place, the formula section answers a practical question: what exactly does the network compute, and how do we adjust every parameter so that its predictions improve? We will proceed in the same order as the implementation. First we define the forward pass and keep track of shapes. Then we define a numerically stable loss. Finally we differentiate that loss layer by layer. The order matters: backpropagation is not a separate learning algorithm, it is the chain rule applied to the forward computation we have just written down.

We begin with notation. Suppose we have nn training examples, each with dd input features. Let xi∈Rdx_i \in \mathbb{R}^d be the ii-th input and yi∈{0,1}y_i \in \{0,1\} its binary label. We use a network with one hidden layer containing hh hidden units. The hidden layer has weight matrix W∈Rh×d\mathbf{W} \in \mathbb{R}^{h \times d} and bias vector b∈Rh\mathbf{b} \in \mathbb{R}^h. The output layer has weight vector v∈Rh\mathbf{v} \in \mathbb{R}^h and bias c∈Rc \in \mathbb{R}.

where:

  • nn: number of training examples, with one example per row when stored in the matrix X\mathbf{X}
  • dd: number of input features per example
  • xix_i: the ii-th input vector, an element of Rd\mathbb{R}^d
  • yiy_i: the binary label of the ii-th example, either 00 or 11
  • hh: number of hidden units in the single hidden layer
  • W\mathbf{W}: hidden-layer weight matrix, whose jj-th row Wj∈Rd\mathbf{W}_j \in \mathbb{R}^d holds the weights feeding hidden unit jj
  • b\mathbf{b}: hidden-layer bias vector, whose jj-th entry bjb_j shifts hidden unit jj
  • v\mathbf{v}: output-layer weight vector, whose jj-th entry vjv_j scales hidden activation aja_j in the output logit
  • cc: output-layer bias, which shifts the logit before the sigmoid

The symbol Rh×d\mathbb{R}^{h \times d} means the set of real matrices with hh rows and dd columns. Each row of W\mathbf{W} is the weight vector for one hidden unit. The bias bjb_j shifts the jj-th hidden unit, just as the intercept shifts a regression line. One way to read the notation is as a contract: the input has dd numbers, the hidden layer is allowed to create hh new numbers, and the output layer must combine those hh numbers into one prediction. The rest of the derivation is about making that contract precise and keeping the dimensions consistent.

Affine layers, nonlinear activations, and shapes

We start with the simplest part: an affine transformation. For a single input xx, the hidden preactivation is

z=Wx+b,z = \mathbf{W}x + \mathbf{b},

where:

  • xx: a single input vector, so that Wx\mathbf{W}x applies the h×dh \times d hidden weight matrix
  • zz: the hidden preactivation vector, the affine output before the nonlinearity

The vector z∈Rhz \in \mathbb{R}^h contains one number per hidden unit. The jj-th component is

zj=∑k=1dWjkxk+bj.z_j = \sum_{k=1}^{d} W_{jk}x_k + b_j.

where:

  • zjz_j: the preactivation of hidden unit jj
  • WjkW_{jk}: the weight connecting input feature kk to hidden unit jj, the entry in row jj and column kk of W\mathbf{W}
  • xkx_k: the kk-th feature of the input
  • bjb_j: the bias of hidden unit jj
  • dd: the number of input features

We read ∑k=1d\sum_{k=1}^{d} as “sum over the input features k=1,…,dk=1,\dots,d.” The entry WjkW_{jk} is the weight connecting input feature kk to hidden unit jj. This is exactly the same weighted sum that appears in linear regression, repeated hh times with its own weights for each hidden unit. The hidden layer is a bank of learned affine projections, which can respond to different directions in the input space. The bias bjb_j shifts the point at which the jj-th projection is centered.

Without a nonlinearity, stacking two affine layers would collapse into one affine layer:

v⊤(Wx+b)+c=(v⊤W)x+(v⊤b+c),\mathbf{v}^\top(\mathbf{W}x+\mathbf{b})+c = (\mathbf{v}^\top\mathbf{W})x + (\mathbf{v}^\top\mathbf{b}+c),

which is still affine (linear plus a constant) in xx. A nonlinear activation allows the composition to represent functions that a single affine layer cannot. A common choice is the hyperbolic tangent,

aj=tanh⁡(zj)=ezj−e−zjezj+e−zj,a_j = \tanh(z_j) = \frac{e^{z_j}-e^{-z_j}}{e^{z_j}+e^{-z_j}},

where:

  • aja_j: the activation of hidden unit jj
  • zjz_j: the preactivation of hidden unit jj entering the activation

The derivative of tanh is

ddzjtanh⁡(zj)=1−tanh⁡2(zj)=1−aj2.\frac{d}{dz_j}\tanh(z_j)=1-\tanh^2(z_j)=1-a_j^2.

Another common choice is the rectified linear unit,

aj=ReLU⁡(zj)=max⁡(0,zj),a_j = \operatorname{ReLU}(z_j)=\max(0,z_j),

where:

  • aja_j: the activation of hidden unit jj
  • zjz_j: the preactivation of hidden unit jj entering the activation

The ReLU derivative is 11 when zj>0z_j>0 and 00 when zj<0z_j<0. At exactly zero the derivative is not defined, and implementations choose a convention, usually 00. The sigmoid activation

σ(z)=11+e−z\sigma(z)=\frac{1}{1+e^{-z}}

where:

  • σ\sigma: the logistic (sigmoid) function mapping any real input to (0,1)(0,1)
  • zz: the input to the sigmoid, for example an output logit

The sigmoid is often used at the output for binary classification, and sometimes in hidden layers. Its derivative is σ(z)(1−σ(z))\sigma(z)(1-\sigma(z)). These derivatives tell us how a small change in a preactivation changes the activation. The backward pass multiplies them by the upstream loss gradient to obtain the gradient with respect to the preactivation. In a saturated region, tanh or sigmoid has a small derivative and attenuates a fixed upstream gradient. A ReLU has derivative zero on the negative side, so its local data-loss gradient is zero for that input.

The figure below makes the local exchange rates visible. Solid curves are the activations, and dashed curves are their derivatives. Where a derivative is near zero, the backward pass transmits very little gradient. The figure also shows that sigmoid and tanh flatten at large magnitudes, while ReLU stays linear on the positive side and becomes exactly zero on the negative side.

The hidden setup below makes the shared plotting module available and seeds the book plots once. Each plotting cell imports the style helpers it uses. The cell after it only prepares the data that the activation figure will display.

PythonIn [3]
CollapseExpand
import numpy as np

z_grid = np.linspace(-4.0, 4.0, 401)
tanh_vals = np.tanh(z_grid)
sigmoid_vals = 1.0 / (1.0 + np.exp(-z_grid))
relu_vals = np.maximum(0.0, z_grid)
tanh_deriv = 1.0 - tanh_vals**2
sigmoid_deriv = sigmoid_vals * (1.0 - sigmoid_vals)
relu_deriv = (z_grid > 0.0).astype(float)
VisualizationOut [4]
CollapseExpand
Curves of tanh, sigmoid, and ReLU activations with dashed local derivatives.
Common hidden-layer activations and their local derivatives. Solid lines show the activation values, and dashed lines show the derivative used by backpropagation. For a fixed upstream loss gradient, a near-zero activation derivative attenuates the gradient passed to the preactivation. This can slow updates through saturated hidden units.

For a mini-batch of BB examples, we store the inputs in a matrix X∈RB×d\mathbf{X} \in \mathbb{R}^{B \times d}, with one example per row, and use the same hidden-layer mapping as in the single-example derivation. The hidden preactivation matrix is

Z=XW⊤+1b⊤,\mathbf{Z} = \mathbf{X}\mathbf{W}^\top + \mathbf{1}\mathbf{b}^\top,

where:

  • BB: the number of examples in the mini-batch
  • X\mathbf{X}: the B×dB \times d input matrix, with one example per row
  • W⊤\mathbf{W}^\top: the d×hd \times h transpose of the hidden weight matrix
  • 1\mathbf{1}: a column vector of ones with length BB
  • b⊤\mathbf{b}^\top: the 1×h1 \times h transpose of the hidden bias, broadcast across rows
  • Z\mathbf{Z}: the B×hB \times h hidden preactivation matrix

The transpose appears because X\mathbf{X} has examples as rows while W\mathbf{W} has hidden units as rows. The product XW⊤\mathbf{X}\mathbf{W}^\top has shape B×hB \times h: one row per example, one column per hidden unit. Broadcasting adds the same bias vector b⊤\mathbf{b}^\top to every row. The activation matrix is A=g(Z)\mathbf{A}=g(\mathbf{Z}), where gg is applied elementwise.

The output logit is

s=Av+c,s = \mathbf{A}\mathbf{v}+c,

where:

  • A\mathbf{A}: the B×hB \times h hidden activation matrix
  • v\mathbf{v}: the h×1h \times 1 output weight vector
  • cc: the output bias
  • ss: the output logit vector of length BB

For binary classification we convert the logit to a probability with the sigmoid:

pi=σ(si)=11+e−si.p_i = \sigma(s_i)=\frac{1}{1+e^{-s_i}}.

where:

  • sis_i: the output logit of example ii
  • pip_i: the predicted probability that example ii belongs to class 11

The shape chain is worth checking: X\mathbf{X} is B×dB \times d, W⊤\mathbf{W}^\top is d×hd \times h, and Z\mathbf{Z} and A\mathbf{A} are B×hB \times h. In the column-vector notation used here, v\mathbf{v} is h×1h \times 1 and ss is B×1B \times 1. The NumPy implementation stores these vectors as one-dimensional arrays with shapes (h,) and (B,); the scalar formulas are the same. Writing each shape beside the corresponding operation helps find dimension mismatches before coding.

Forward passes and stable losses

The forward pass is the sequence of operations that turns inputs into predictions. For one mini-batch we compute Z\mathbf{Z}, then A=g(Z)\mathbf{A}=g(\mathbf{Z}), then s=Av+cs=\mathbf{A}\mathbf{v}+c, then p=σ(s)p=\sigma(s). The forward pass stores X\mathbf{X}, Z\mathbf{Z}, and A\mathbf{A} in a cache. This tanh backward pass reuses A\mathbf{A} to compute the activation derivatives elementwise as 1−aij21-a_{ij}^2; it receives X\mathbf{X} separately and does not read the cached Z\mathbf{Z}. It is useful to think of the forward pass as building a cache: every quantity that will be needed later is stored now, so the backward pass can reuse it instead of recomputing it.

For binary labels, the negative log-likelihood of one example is

ℓi=−[yilog⁡pi+(1−yi)log⁡(1−pi)].\ell_i = -\left[y_i\log p_i + (1-y_i)\log(1-p_i)\right].

where:

  • ℓi\ell_i: the binary cross-entropy loss for example ii
  • yiy_i: the binary label, either 00 or 11
  • pip_i: the predicted probability of class 11 for example ii

This is the binary cross-entropy loss. If yi=1y_i=1, only −log⁡pi-\log p_i remains; if yi=0y_i=0, only −log⁡(1−pi)-\log(1-p_i) remains. The loss is small when the predicted probability agrees with the label and large when it disagrees. In that sense the loss is a precise way of saying “how surprised should the model be by the observed label?”

For a very negative logit, a naive sigmoid calculation can overflow in e−sie^{-s_i} and round the predicted probability to zero. Taking its logarithm then produces negative infinity even though the mathematical log probability is finite. We compute the loss from the logit instead. Since p=σ(s)=1/(1+e−s)p=\sigma(s)=1/(1+e^{-s}), we have

−log⁡p=log⁡(1+e−s)-\log p = \log(1+e^{-s})

and

−log⁡(1−p)=log⁡(1+es).-\log(1-p) = \log(1+e^{s}).

where:

  • pp: the predicted probability for the example, equal to σ(s)\sigma(s)
  • ss: the output logit for the example

Combining the two cases gives

ℓi=log⁡(1+esi)−yisi.\ell_i = \log(1+e^{s_i}) - y_i s_i.

where:

  • ℓi\ell_i: the binary cross-entropy loss for example ii, computed from the logit
  • sis_i: the output logit of example ii
  • yiy_i: the binary label, either 00 or 11

The expression log⁡(1+esi)\log(1+e^{s_i}) is exactly log⁡(e0+esi)\log(e^0+e^{s_i}), which is a log-sum-exp written in the form log⁡(e0+esi)\log(e^0 + e^{s_i}). Numerical libraries provide a stable function often called logaddexp, which computes log⁡(ea+eb)\log(e^a+e^b) without overflowing. Thus we compute

ℓi=logaddexp⁡(0,si)−yisi.\ell_i = \operatorname{logaddexp}(0,s_i) - y_i s_i.

For label 1 the loss decreases as the logit grows; for label 0 it increases. The logaddexp calculation avoids forming an overflowing exponential directly. The plotted losses remain finite over the displayed logit range.

PythonIn [5]
CollapseExpand
import numpy as np

s_curve = np.linspace(-5.0, 5.0, 401)
loss_label_one = np.logaddexp(0.0, s_curve) - 1.0 * s_curve
loss_label_zero = np.logaddexp(0.0, s_curve) - 0.0 * s_curve
VisualizationOut [6]
CollapseExpand
Two curves showing binary cross-entropy loss against the logit for labels zero and one.
Binary cross-entropy as a function of the output logit for each binary label. For label 1 the loss decreases as the logit grows, while for label 0 it increases. The stable logit form stays finite and grows approximately linearly for confident mistakes.

where:

  • logaddexp⁡(a,b)\operatorname{logaddexp}(a,b): a numerically stable computation of log⁡(ea+eb)\log(e^a+e^b)
  • sis_i: the output logit of example ii
  • yiy_i: the binary label, either 00 or 11

For a batch we average:

L=1B∑i=1Bℓi.L=\frac{1}{B}\sum_{i=1}^{B}\ell_i.

where:

  • LL: the mean binary cross-entropy over the BB examples
  • BB: the number of examples in the batch
  • ℓi\ell_i: the binary cross-entropy loss for example ii

The same idea extends to multiclass classification. If the network produces logits si1,…,siKs_{i1},\dots,s_{iK} for KK classes, the softmax probability of class kk is

p^ik=esik∑m=1Kesim,\hat p_{ik} = \frac{e^{s_{ik}}}{\sum_{m=1}^{K}e^{s_{im}}},

where:

  • p^ik\hat p_{ik}: the predicted probability that example ii belongs to class kk
  • siks_{ik}: the logit for class kk on example ii
  • KK: the number of classes

For this multiclass formula, let yi∈{1,…,K}y_i\in\{1,\dots,K\} denote the true class index, replacing the earlier binary encoding. The multiclass cross-entropy is

ℓi=−si,yi+log⁡∑m=1Kesim.\ell_i = -s_{i,y_i} + \log\sum_{m=1}^{K}e^{s_{im}}.

where:

  • ℓi\ell_i: the cross-entropy loss for example ii
  • KK: the number of classes
  • sims_{im}: the logit for class mm on example ii
  • si,yis_{i,y_i}: the logit for the true class yiy_i on example ii

The second term is computed with a stable log-sum-exp operation. In this chapter we focus on the binary case, but the backward pass for softmax cross-entropy has the same clean form: the gradient with respect to the logits is predicted probability minus one-hot label.

Backpropagation and gradient checking

Backpropagation is the chain rule applied from the output backward. We first compute the derivative of the loss with respect to the output logit sis_i. A useful discipline is to derive the gradient for one scalar example first, then average over the batch; the only change is the factor 1/B1/B, which appears in the delta defined below. For one example,

∂ℓ∂s=∂ℓ∂p∂p∂s.\frac{\partial \ell}{\partial s} = \frac{\partial \ell}{\partial p}\frac{\partial p}{\partial s}.

where:

  • ℓ\ell: the binary cross-entropy loss for one example
  • ss: the output logit for that example
  • p=σ(s)p=\sigma(s): the predicted probability for that example

We read ∂ℓ/∂s\partial \ell/\partial s as the partial derivative of the loss with respect to the logit ss. The derivative of the binary cross-entropy with respect to pp is

∂ℓ∂p=−yp+1−y1−p.\frac{\partial \ell}{\partial p} = -\frac{y}{p}+\frac{1-y}{1-p}.

where:

  • ℓ\ell: the binary cross-entropy loss for one example
  • pp: the predicted probability for that example
  • yy: the binary label of that example

The derivative of the sigmoid is ∂p/∂s=p(1−p)\partial p/\partial s=p(1-p). Multiplying gives

∂ℓ∂s=(−yp+1−y1−p)p(1−p)=p−y.\frac{\partial \ell}{\partial s} = \left(-\frac{y}{p}+\frac{1-y}{1-p}\right)p(1-p) = p-y.

where:

  • ∂ℓ/∂s\partial \ell/\partial s: the derivative of the loss with respect to the logit
  • pp: the predicted probability
  • yy: the binary label

This is a simple result: the gradient at the logit is the predicted probability minus the label. If the network predicts p=0.9p=0.9 and the label is 11, the gradient is −0.1-0.1, so gradient descent increases the logit slightly. If the label is 00, the gradient is 0.90.9, a larger correction. The same pattern will reappear in multiclass classification, where the gradient is the predicted probability vector minus the one-hot label.

For a batch with mean loss, we divide by BB. Define

δi=pi−yiB.\delta_i = \frac{p_i-y_i}{B}.

where:

  • δi\delta_i: the scaled output delta for example ii
  • pip_i: the predicted probability for example ii
  • yiy_i: the binary label for example ii
  • BB: the number of examples in the batch, so division by BB reflects the mean loss

The gradient with respect to the output weights is

∂L∂vj=∑i=1Bδiaij,\frac{\partial L}{\partial v_j} = \sum_{i=1}^{B}\delta_i a_{ij},

where:

  • LL: the mean loss over the batch
  • vjv_j: the jj-th output weight
  • aija_{ij}: the activation of hidden unit jj on example ii

This holds because si=∑jvjaij+cs_i=\sum_j v_j a_{ij}+c, so ∂si/∂vj=aij\partial s_i/\partial v_j=a_{ij}. In matrix form,

∇vL=A⊤δ,\nabla_{\mathbf{v}}L = \mathbf{A}^\top \delta,

where:

  • ∇vL\nabla_{\mathbf{v}}L: the gradient of the mean loss with respect to the output weight vector
  • A\mathbf{A}: the B×hB \times h hidden activation matrix
  • δ\delta: the B×1B \times 1 vector of δi\delta_i values

The transpose is needed because A\mathbf{A} is B×hB \times h and δ\delta is B×1B \times 1, so A⊤δ\mathbf{A}^\top\delta is h×1h \times 1, matching v\mathbf{v}. The gradient with respect to the output bias is

∂L∂c=∑i=1Bδi,\frac{\partial L}{\partial c}=\sum_{i=1}^{B}\delta_i,

where:

  • cc: the output bias
  • δi\delta_i: the scaled output delta for example ii

Now we propagate backward into the hidden layer. For hidden unit jj and example ii, the logit depends on aija_{ij} through si=∑jvjaij+cs_i=\sum_j v_j a_{ij}+c, so

∂L∂aij=δivj.\frac{\partial L}{\partial a_{ij}}=\delta_i v_j.

where:

  • ∂L/∂aij\partial L/\partial a_{ij}: the derivative of the mean loss with respect to the activation of hidden unit jj on example ii
  • δi\delta_i: the scaled output delta for example ii
  • vjv_j: the output weight for hidden unit jj

The activation aij=g(zij)a_{ij}=g(z_{ij}) contributes its local derivative:

∂L∂zij=δivj g′(zij).\frac{\partial L}{\partial z_{ij}} = \delta_i v_j\,g'(z_{ij}).

where:

  • ∂L/∂zij\partial L/\partial z_{ij}: the derivative of the mean loss with respect to the preactivation of hidden unit jj on example ii
  • δi\delta_i: the scaled output delta for example ii
  • vjv_j: the output weight for hidden unit jj
  • g′(zij)g'(z_{ij}): the derivative of the hidden activation evaluated at the preactivation

For tanh⁡\tanh, g′(zij)=1−aij2g'(z_{ij})=1-a_{ij}^2. Define the hidden delta matrix

Δij=δivj (1−aij2),\Delta_{ij} = \delta_i v_j\,(1-a_{ij}^2),

where:

  • Δij\Delta_{ij}: the hidden delta for hidden unit jj on example ii
  • δi\delta_i: the scaled output delta for example ii
  • vjv_j: the output weight for hidden unit jj
  • aija_{ij}: the activation of hidden unit jj on example ii

In matrix notation,

Δ=(δv⊤)⊙(1−A⊙A),\Delta = (\delta\mathbf{v}^\top)\odot(1-\mathbf{A}\odot\mathbf{A}),

where:

  • Δ\Delta: the B×hB \times h hidden delta matrix
  • δ\delta: the B×1B \times 1 vector of scaled output deltas
  • v\mathbf{v}: the h×1h \times 1 output weight vector, so δv⊤\delta\mathbf{v}^\top is a B×hB \times h outer product
  • A\mathbf{A}: the B×hB \times h hidden activation matrix
  • ⊙\odot: elementwise (Hadamard) multiplication

The outer product δv⊤\delta\mathbf{v}^\top has shape B×hB \times h, and 1−A⊙A1-\mathbf{A}\odot\mathbf{A} has the same shape. The hidden preactivation is zij=∑kWjkxik+bjz_{ij}=\sum_k W_{jk}x_{ik}+b_j, so

∂L∂Wjk=∑i=1BΔijxik,∂L∂bj=∑i=1BΔij.\frac{\partial L}{\partial W_{jk}} = \sum_{i=1}^{B}\Delta_{ij}x_{ik}, \qquad \frac{\partial L}{\partial b_j} = \sum_{i=1}^{B}\Delta_{ij}.

where:

  • ∂L/∂Wjk\partial L/\partial W_{jk}: the derivative of the mean loss with respect to the hidden weight connecting input feature kk to hidden unit jj
  • ∂L/∂bj\partial L/\partial b_j: the derivative of the mean loss with respect to the hidden bias of unit jj
  • Δij\Delta_{ij}: the hidden delta for hidden unit jj on example ii
  • xikx_{ik}: the kk-th feature of example ii

In matrix form,

∇WL=Δ⊤X,∇bL=Δ⊤1.\nabla_{\mathbf{W}}L = \Delta^\top \mathbf{X}, \qquad \nabla_{\mathbf{b}}L = \Delta^\top \mathbf{1}.

where:

  • ∇WL\nabla_{\mathbf{W}}L: the gradient of the mean loss with respect to the hidden weight matrix
  • ∇bL\nabla_{\mathbf{b}}L: the gradient of the mean loss with respect to the hidden bias vector
  • Δ⊤\Delta^\top: the h×Bh \times B transpose of the hidden delta matrix
  • X\mathbf{X}: the B×dB \times d input matrix
  • 1\mathbf{1}: the B×1B \times 1 column vector of ones

Again the shapes match: Δ⊤\Delta^\top is h×Bh \times B, X\mathbf{X} is B×dB \times d, so Δ⊤X\Delta^\top\mathbf{X} is h×dh \times d, the same shape as W\mathbf{W}. The gradient with respect to b\mathbf{b} is the column sum of Δ\Delta. Notice how each matrix expression encodes a sum: the transpose aligns examples with the quantity being summed, and the matrix product performs the sum over examples in one operation.

If we add L2 regularization, the loss becomes

Lreg=L+λ2(∑j,kWjk2+∑jvj2).L_{\text{reg}} = L + \frac{\lambda}{2}\left(\sum_{j,k}W_{jk}^2+\sum_j v_j^2\right).

where:

  • LregL_{\text{reg}}: the regularized mean loss
  • LL: the unregularized mean binary cross-entropy
  • λ\lambda: the L2 regularization strength, with λ≥0\lambda \geq 0
  • WjkW_{jk}: the hidden weight connecting input feature kk to hidden unit jj
  • vjv_j: the output weight for hidden unit jj

The factor 1/21/2 makes the derivative of the penalty with respect to WjkW_{jk} equal to λWjk\lambda W_{jk}, and similarly for vjv_j. We do not regularize the biases by default, because they do not control the scale of the learned features in the same way.

Gradient checking verifies the backward pass by comparing analytic gradients with finite differences. It is the unit test of a hand-written backward pass. For a parameter θi\theta_i,

∂L∂θi≈L(θi+ϵ)−L(θi−ϵ)2ϵ.\frac{\partial L}{\partial \theta_i} \approx \frac{L(\theta_i+\epsilon)-L(\theta_i-\epsilon)}{2\epsilon}.

where:

  • θi\theta_i: the ii-th scalar parameter being checked
  • L(θi+ϵ)L(\theta_i+\epsilon): the loss with parameter θi\theta_i increased by the perturbation size ϵ\epsilon
  • L(θi−ϵ)L(\theta_i-\epsilon): the loss with parameter θi\theta_i decreased by ϵ\epsilon
  • ϵ\epsilon: the finite-difference step size

Perturb one parameter by ϵ\epsilon in each direction, compute the two losses, and divide their difference by 2ϵ2\epsilon. For a sufficiently smooth loss, the centered formula has truncation error of order ϵ2\epsilon^2. Floating-point cancellation grows as the step becomes too small, so this is not a guarantee of greater accuracy for every step size. A relative error below about 10−410^{-4} is a useful diagnostic for a smooth float64 example at a suitable step size, but near-zero gradients and activation kinks need separate inspection.

Mathematical Properties

With a sufficiently wide hidden layer, a suitable continuous sigmoidal activation, and a linear output, a network can approximate continuous functions on a compact input domain to arbitrary accuracy. This is an existence statement about a family of functions, not a guarantee that gradient descent will find the required parameters from finite data. Our binary classifier instead uses a sigmoid output to keep predictions between zero and one. Approximation capacity does not remove the need for regularization and validation.

The joint loss is generally nonconvex in W\mathbf{W}, b\mathbf{b}, v\mathbf{v}, and cc. It also has a permutation symmetry: permuting hidden units and applying the same permutation to rows of W\mathbf{W}, entries of b\mathbf{b}, and entries of v\mathbf{v} leaves the network output unchanged. Distinct parameter vectors can therefore represent the same function. Random initialization helps give hidden units different starting points. If every weight and bias in this tanh network starts at zero, hidden activations and output weights are zero; the hidden features cannot begin learning under the stated gradient updates.

The gradient with respect to WjkW_{jk} contains the input factor xkx_k. Holding the other gradient factors fixed, rescaling that feature rescales this gradient. Standardization brings marginal feature scales closer together, but it does not remove correlations or guarantee a well-conditioned loss. Saturating tanh and sigmoid activations have small local derivatives at large magnitudes. These multipliers can attenuate gradient flow; ReLU avoids positive-side saturation but has zero derivative on its negative side.

Comments

Add to the conversation

A question, a correction, or an example from your own work.

No comments yet. Be the first to share your thoughts!

Newsletter

Stay up to date

Get new articles, book updates, and notes on AI and technology.

Unsubscribe at any time. Privacy policy