Worked examples — TensorFlow - Keras basics
This page is a drill. We take the machinery from TensorFlow / Keras basics and push a number through every kind of situation it can hand you — every shape, every zero, every degenerate case, a word problem, and an exam trap. Nothing here needs code to run; we do the arithmetic by hand so you see what the framework does silently.
Before we start, one promise: every symbol is earned. When we write , , , cross-entropy, or "parameter count", we will have already drawn what it means below.
The scenario matrix
Think of this topic as a machine with knobs. Each knob can sit in a normal position, a boundary position, or a broken position. The table lists every knob-class we must cover. Each worked example is tagged with the cell it hits.
| # | Case class | The "normal" case | The edge / degenerate case we must also show |
|---|---|---|---|
| A | Tensor shape / rank | matrix (rank 2) | scalar (rank 0), single flattened image (rank 1), a batch dimension |
| B | Dense forward pass | positive weighted sum | a zero input vector, negative pre-activation |
| C | ReLU activation | positive passes through | negative clipped to 0 (the "dead" side) |
| D | Softmax | spread-out logits | all-equal logits (max entropy), one huge logit (saturation + numerical stability) |
| E | Cross-entropy loss | confident-correct (small loss) | confident-wrong (huge loss), the perfect prediction (loss ) |
| F | Dropout scaling | training: scale by | inference: identity (no scaling), and limits |
| G | Parameter counting | one Dense layer | a whole Sequential stack, a bias-free layer |
| H | Gradient step | one Adam/SGD update | learning rate too big (overshoot), gradient = 0 (stuck) |
| I | Word problem | — | design a model end-to-end from a spec |
| J | Exam twist | — | shape-mismatch trap, training=True vs False |
Prerequisites we lean on: 3.3.01-Neural-Network-Basics, 3.07-Activation-Functions, 3.1.01-Gradient-Descent, 3.2.03-Backpropagation, 3.4.05-Overfitting-Regularization.
Building the picture first
Every example below lives on this one diagram: an input vector enters a Dense layer, gets a weighted sum, passes an activation, and (for classification) a softmax turns the numbers into probabilities.

Keep that figure in your head; we point back to it constantly. (Every example below reads the columns of as "the wires into neuron " — consistent with the index above.)
Example 1 — Case A: shapes, from scalar to image batch
Forecast: guess each shape before reading on. How many numbers total does the image batch hold?
- Loss
4.2— no indices needed to reach it. Why this step? Rank counts how many indices you must supply to pick one number; a lone number needs zero. → rank 0, shape(). [1,2,3]— one index picks an element. → rank 1, shape(3,).2×2matrix — need a row index and a column index. → rank 2, shape(2,2).- One flattened MNIST image — the
28×28grid is unrolled into a single long list of numbers; one index picks a pixel. → rank 1, shape(784,). Why this step? A Dense layer multiplies one flat vector by ; flattening is what turns the 2-D image into that vector. - Batch of 32 such images — stack the 32 length-784 vectors along a new batch axis in front. → shape
(32, 784), rank 2. Why this step? Dense layers eat rows: one row = one example. The batch axis is always first in Keras.
Verify: total numbers in the batch . A single flattened image has pixels, and . ✓
Example 2 — Case B + C: one Dense neuron, zero input and the negative (dead ReLU) side
Forecast: with ReLU = "keep positives, zero out negatives", predict which neuron dies in case (a).
Here — read the columns of as "wires into neuron " (this is exactly the convention from the definition above: column = weights into neuron ; look at the middle of the figure).
- Case (a), neuron 1: . Why? Column 1 of is . ReLU.
- Case (a), neuron 2: . Column 2 is . ReLU. → output .
- Case (b) zero input: the sum vanishes, so . Thus . Why this matters: with no signal, the bias is the pre-activation — bias sets the neuron's resting level.
- ReLU. Neuron 2 is dead here: negative → exactly 0. That is the flat left arm of ReLU.
Verify: ReLU. , , , . ✓ See 3.07-Activation-Functions for why the flat side can permanently kill a neuron.
Example 3 — Case D: softmax in three regimes (and the stability trick)

Forecast: for the all-equal case, what must the answer be by symmetry? For the dominant case, how close to 1 does the winner get?
The bars in the figure are the three probability outputs.
- (a) spread. Compute ; sum . → . Why exponential? It is positive and monotone, so it keeps ordering while forcing positivity — the three softmax requirements from the parent note.
- (b) all-equal. Every is identical, so each fraction is . → . Why this step? Equal evidence must give equal probability — softmax respects symmetry; this is the maximum-entropy (most uncertain) output.
- (c) dominant. dwarfs the two . → . Why show this: softmax saturates — a big logit gap pushes probability toward 1, which flattens gradients (a training concern).
- Numerical-stability edge case. Imagine logits
[1000, 999, 998]. Then overflows to infinity on a computer, and isNaN. The fix tf.keras uses silently: subtract the max first — replace each by . Here that gives[0, -1, -2], all , so every is safely in . Why the answer is unchanged: multiplying numerator and denominator by the same constant cancels: . Same probabilities, no overflow.
Verify: each vector sums to 1: ; ; . And the shifted softmax of [1000,999,998] equals the (identical) softmax of [0,-1,-2]. ✓
Example 4 — Case E: cross-entropy across correct, wrong, and perfect
Forecast: which case blows up? Which drives loss toward zero?
- (a) correct. . Why only ? The one-hot label is 1 on the true class and 0 elsewhere, so every other term drops out — cross-entropy only ever grades the probability you assigned to the right answer.
- (b) wrong. True-class prob is : . Why so large? explodes as its input ; the loss punishes confident mistakes hard. This is the gradient signal that fixes the model.
- (c) perfect. . Why zero? No surprise, no penalty — the limiting best case.
Verify: , , . Wrong loss correct loss perfect. ✓ (These are the numbers SparseCategoricalCrossentropy() returns per example.)
Example 5 — Case F: dropout scaling, train vs inference, and the limits
Forecast: why does the kept value get bigger, not stay the same, during training?
Rule: training keeps a unit with prob and rescales it by ; drops otherwise. Inference does nothing.
- Training draw (drop units 2,3): survivors scale by . → . Why scale up by 2? Half the inputs vanished, so to keep the expected total unchanged we double the survivors.
- Expected value check (the "why"): . For : . Mean is preserved — that is the whole point of inverted dropout.
- Inference:
training=False, so dropout is the identity → output is exactly . Why: we want deterministic, full-signal predictions at test time. - Limits: → scale , nothing dropped (dropout off). → scale and almost everything zeroed (network destroyed — useless). Sane lives in .
Verify: kept value ; . ✓ More on this in 3.4.05-Overfitting-Regularization.
Example 6 — Case G: counting parameters of a whole Sequential stack
Forecast: does Dropout add any parameters? Guess the total order of magnitude.
A Dense layer with inputs and outputs has weights biases.
- Layer 1: . Why ? one bias per output neuron.
- Dropout: parameters. Why? It only masks/scales; there is nothing to learn.
- Layer 2: .
- Layer 3: .
- Total: .
- Bias-free variant of layer 1: drop its 128 biases → , so grand total .
Verify: ; sum ; bias-free total . ✓ This matches model.summary()'s "Total params".
Example 7 — Case H: one gradient-descent update, and the two failure modes
Forecast: does one small step move toward 5? Does the big step help or hurt?
The derivative tells us the slope: negative slope means "go right to descend."
- Gradient at : . Why the minus sign matters: gradient points uphill; we step opposite it.
- Good step (): . Loss went . Closer to 5. ✓
- Overshoot (): . Loss went — worse. Why: too-big jumps past the valley and climbs the far wall; this is divergence.
- At the minimum (): gradient , so the update leaves unchanged. Why: zero slope = flat ground = nowhere to descend. (Real Adam behaves richer, but the SGD skeleton is this.)
Verify: step-down: ; loss . Overshoot: ; loss . Minimum: gradient . ✓ Foundations in 3.1.01-Gradient-Descent and 3.2.03-Backpropagation.
Example 8 — Case I: word problem, design the whole model
Forecast: why is the output activation not softmax here?
- Input shape
(20,). One row per customer, 20 numbers wide. - Hidden: two ReLU Dense layers, 16 then 8 units — non-linearity so stacked layers don't collapse into one linear map.
- Output:
Dense(1, activation='sigmoid'). Why sigmoid not softmax? We need one probability, not a distribution over classes. Sigmoid squashes any real number into — perfect for "probability of the single event default." - Loss:
BinaryCrossentropy— the two-outcome sibling of the loss in Example 4. - Param count: .
Verify: ; ; ; total . A sigmoid output in is a valid probability. ✓
Example 9 — Case J: two exam traps (shape mismatch & the training flag)
Forecast: how many numbers does one MNIST image have, and how many does the Dense layer expect per row?
Trap (a) — the shape mismatch:
- What the layer expects.
Dense(128, input_shape=(784,))builds a weight matrix , so it wants each example to be a flat length-784 row. Why: a Dense layer computes ; that matrix product only lines up if has 784 entries. - What you actually fed. The raw tensor
(32, 28, 28)gives each example as a rank-228×28block, not a flat vector. Why it fails: Keras raises a shape/rank error — it cannot multiply a 2-D block by a 2-D weight matrix along a length-784 axis that isn't there. - The fix. Insert
keras.layers.Flatten()as the first layer (or reshape to(32, 784)yourself). This unrolls each28×28image into length — exactly Example 1, step 4. Why nothing is lost: flattening only relabels the same 784 pixels as one long row; no pixel is dropped.
Trap (b) — training=True vs False:
- What causes the randomness. Dropout (Example 5) randomly zeros units — but only when it runs in training mode. If your custom
callhard-codesself.dropout(x, training=True), dropout keeps sampling a fresh random mask on every forward pass, so the same input gives different outputs. Why: you asked it to drop units even at test time. - The fix. Let the
trainingflag flow through:self.dropout(x, training=training), and call the model withtraining=Falseat inference (whichmodel.evaluate/model.predictdo automatically). Withtraining=False, dropout's keep-probability is , so it becomes the identity — deterministic, full-signal outputs. Why this is correct: at test time we want the model's honest, stable prediction, not a randomly thinned one.
Verify: (the flatten fix is exact); with training=False, dropout keep-prob and scale , so it is the identity → deterministic output. ✓
Recall Self-check (reveal after answering)
Softmax of all-equal logits [5,5,5]? ::: — equal evidence, equal probability.
Cross-entropy loss for a perfect prediction on the true class? ::: .
Params in Dense(64) fed by 128 inputs? ::: .
Why divide by in dropout? ::: to keep (preserve expected activation).
Output activation for a single-probability default model? ::: sigmoid, not softmax.
ReLU of a pre-activation? ::: — the negative side is clipped to zero.
Why subtract before softmax? ::: to avoid overflow; the probabilities are unchanged.
Related build-outs: 3.3.09-PyTorch-basics (same math, different steering wheel) and 4.2.01-CNN-Architecture (where the Flatten trap in Example 9 gets replaced by convolutions).