LSTMs and GRUs

Imagine training a network to predict the next word in a paragraph. The crucial clue appeared a hundred words earlier. A plain Recurrent Neural Network trained with Backpropagation Through Time tries to carry that information forward. It does this through a hundred repeated multiplications. The signal either explodes or, far more often, decays into numerical silence. This is the vanishing gradient problem. It is not a minor nuisance. It is the reason vanilla RNNs are effectively short-memory systems. This holds no matter how large you make their hidden state. Long Short-Term Memory (LSTM) networks, introduced in 1997, and Gated Recurrent Units (GRUs), introduced in 2014, solve this by redesigning the recurrence itself. Instead of forcing information through a single nonlinear squashing function at every timestep, they introduce a separate memory pathway. This is a cell state or hidden state that gates can write to, read from, and protect. It is controlled by learned gates that decide what to remember, what to forget, and what to output. The gates are themselves small neural networks. They are trained end-to-end alongside everything else. So the model learns its own memory policy from data, rather than having one hand-engineered. This idea mattered enormously in practice. Before attention-based and transformer architectures dominated, LSTMs powered production systems. They ran machine translation, speech recognition, and handwriting recognition at Google, Apple, and Baidu. GRUs offered a lighter-weight alternative with comparable performance and fewer parameters. This was useful when compute or memory was tight. Even today, gated recurrent architectures remain a strong, simple baseline. This holds in domains with strict latency budgets, streaming requirements, or modest data. This article explains precisely how the gates are computed. It shows why the additive cell-state update is the mathematical key to preventing gradient vanishing. It walks through a full numerical trace of an LSTM cell. It compares LSTM against GRU design tradeoffs. Finally, it situates both historically, before they gave way to attention mechanisms in Encoder-Decoder Architectures.

Key takeaways
  • LSTMs and GRUs replace the single RNN recurrence with gated units that control information flow explicitly.
  • The LSTM cell state is updated additively (via forget and input gates), which is the key fix for vanishing gradients.
  • GRUs merge the cell and hidden state into one vector and use only two gates, trading some expressiveness for efficiency.
  • Both process sequences in O(T)O(T) time and O(1)O(1) per-step memory beyond the hidden state, same asymptotic cost as vanilla RNNs.
  • Gate values are learned functions of input and previous hidden state, giving data-driven, per-dimension memory control.
  • They were the dominant sequence architecture for a decade before being displaced by attention-based transformers.
The core insight

Gated recurrent units fix vanishing gradients by letting information flow through an additive, gate-controlled memory path instead of a single repeatedly-squashed nonlinear recurrence.

The idea

A vanilla RNN updates its hidden state as ht=tanh⁡(Whht−1+Wxxt+b)h_t = \tanh(W_h h_{t-1} + W_x x_t + b). During backpropagation through time, the gradient of the loss with respect to ht−kh_{t-k} involves a product of kk Jacobians, each roughly Wh⊤diag⁡(tanh⁡′(⋅))W_h^\top \operatorname{diag}(\tanh'(\cdot)). Since ∣tanh⁡′∣≤1|\tanh'| \le 1 and is typically much smaller away from the origin, and since repeated multiplication by the same (or similarly-scaled) matrix tends to shrink or blow up singular values geometrically, the gradient magnitude scales roughly like λk\lambda^k for some effective factor λ\lambda. For λ<1\lambda < 1 this vanishes exponentially in kk; for λ>1\lambda > 1 it explodes. This is the vanishing/exploding gradient problem, and it means vanilla RNNs cannot reliably learn dependencies spanning more than a few dozen steps. The LSTM (Long Short-Term Memory) fixes this by introducing a separate cell state ctc_t that is updated by addition rather than repeated nonlinear transformation:

ct=ft⊙ct−1+it⊙c~tc_t = f_t \odot c_{t-1} + i_t \odot \tilde{c}_t

Here ftf_t (the forget gate) and iti_t (the input gate) are vectors in (0,1)d(0,1)^d, produced by sigmoid layers, and c~t\tilde c_t is a candidate update. Because this update is additive rather than a matrix-multiply-then-squash, the gradient ∂ct/∂ct−1=ft\partial c_t / \partial c_{t-1} = f_t (elementwise), with no forced contraction from a shared weight matrix. If the network learns ft≈1f_t \approx 1 for the dimensions that must persist, gradients flow through those dimensions almost unchanged across arbitrarily many steps — this is the mechanism, not a heuristic, that mitigates vanishing gradients. A separate hidden state (output) hth_t is derived from the cell state via an output gate oto_t: ht=ot⊙tanh⁡(ct)h_t = o_t \odot \tanh(c_t). All three gates and the candidate are computed from the same inputs (xt,ht−1)(x_t, h_{t-1}) via learned affine transforms followed by nonlinearities — sigmoids for gates (bounding them to act as soft switches in [0,1][0,1]), tanh⁡\tanh for the candidate content (bounding value magnitude to [−1,1][-1,1] for stability). The GRU (Gated Recurrent Unit) simplifies this design by merging the cell state and hidden state into a single vector hth_t, and using only two gates: an update gate ztz_t (playing a role similar to a combined forget/input gate) and a reset gate rtr_t (controlling how much past information is used when computing the candidate). This yields comparable gradient-flow benefits with fewer parameters and one fewer state vector to carry, at the cost of slightly less fine-grained control over memory (no independent input/forget/output decisions).

How it works

LSTM cell. At each timestep tt, given input xt∈Rnx_t \in \mathbb{R}^n, previous hidden state ht−1∈Rdh_{t-1} \in \mathbb{R}^d, and previous cell state ct−1∈Rdc_{t-1} \in \mathbb{R}^d, compute:

ft=σ(Wfxt+Ufht−1+bf)(forget gate)it=σ(Wixt+Uiht−1+bi)(input gate)ot=σ(Woxt+Uoht−1+bo)(output gate)c~t=tanh⁡(Wcxt+Ucht−1+bc)(candidate cell content)ct=ft⊙ct−1+it⊙c~t(cell state update)ht=ot⊙tanh⁡(ct)(hidden state / output)\begin{aligned} f_t &= \sigma(W_f x_t + U_f h_{t-1} + b_f) &&\text{(forget gate)}\\ i_t &= \sigma(W_i x_t + U_i h_{t-1} + b_i) &&\text{(input gate)}\\ o_t &= \sigma(W_o x_t + U_o h_{t-1} + b_o) &&\text{(output gate)}\\ \tilde c_t &= \tanh(W_c x_t + U_c h_{t-1} + b_c) &&\text{(candidate cell content)}\\ c_t &= f_t \odot c_{t-1} + i_t \odot \tilde c_t &&\text{(cell state update)}\\ h_t &= o_t \odot \tanh(c_t) &&\text{(hidden state / output)} \end{aligned}

GRU cell. Given xtx_t and ht−1h_{t-1} only (no separate cell state):

zt=σ(Wzxt+Uzht−1+bz)(update gate)rt=σ(Wrxt+Urht−1+br)(reset gate)h~t=tanh⁡(Whxt+Uh(rt⊙ht−1)+bh)(candidate hidden state)ht=(1−zt)⊙ht−1+zt⊙h~t(hidden state update)\begin{aligned} z_t &= \sigma(W_z x_t + U_z h_{t-1} + b_z) &&\text{(update gate)}\\ r_t &= \sigma(W_r x_t + U_r h_{t-1} + b_r) &&\text{(reset gate)}\\ \tilde h_t &= \tanh(W_h x_t + U_h (r_t \odot h_{t-1}) + b_h) &&\text{(candidate hidden state)}\\ h_t &= (1 - z_t) \odot h_{t-1} + z_t \odot \tilde h_t &&\text{(hidden state update)} \end{aligned}

The GRU's hth_t update is structurally identical to the LSTM's ctc_t update — a convex combination controlled by a gate — which is exactly what preserves the additive gradient path. The reset gate rtr_t additionally lets the network "forget" past context specifically when forming the candidate, without discarding ht−1h_{t-1} itself in the final blend. ``` function LSTM_STEP(x_t, h_prev, c_prev, params):

# params bundles W_, U_, b_ for f, i, o, c f_t = sigmoid(params.Wf @ x_t + params.Uf @ h_prev + params.bf) i_t = sigmoid(params.Wi @ x_t + params.Ui @ h_prev + params.bi) o_t = sigmoid(params.Wo @ x_t + params.Uo @ h_prev + params.bo) c_tilde = tanh(params.Wc @ x_t + params.Uc @ h_prev + params.bc) c_t = f_t c_prev + i_t c_tilde # elementwise; additive update h_t = o_t tanh(c_t) return h_t, c_t

function GRU_STEP(x_t, h_prev, params): z_t = sigmoid(params.Wz @ x_t + params.Uz @ h_prev + params.bz) r_t = sigmoid(params.Wr @ x_t + params.Ur @ h_prev + params.br) h_tilde = tanh(params.Wh @ x_t + params.Uh @ (r_t h_prev) + params.bh) h_t = (1 - z_t) h_prev + z_t * h_tilde return h_t

function RUN_SEQUENCE(inputs x_1..x_T, params, cell_type): h = zeros(d) c = zeros(d) # unused for GRU outputs = [] for t in 1..T: if cell_type == LSTM: h, c = LSTM_STEP(x_t, h, c, params) else: h = GRU_STEP(x_t, h, params) outputs.append(h) return outputs # feed into loss / next layer ``` Training proceeds exactly as with a vanilla RNN: unroll the recurrence across TT timesteps, compute a loss on the outputs, and run Backpropagation Through Time to get gradients with respect to all shared weight matrices W∗,U∗,b∗W_*, U_*, b_*. The only difference from a vanilla RNN is the richer local computational graph at each timestep — more nodes, but each still O(d2)O(d^2) work and the chain rule still applies mechanically.

Figure
LSTM cell: gates control the additive cell-state highway
c_{t-1} c_t cell state (additive highway) × f_t (σ) + × i_t (σ) c̃_t (tanh) × o_t (σ) tanh(c_t) h_t x_t , h_{t-1}

Complexity & correctness

Time complexity. At each timestep, an LSTM computes four affine transforms of size O(d(d+n))O(d(d+n)) (each gate/candidate uses a d×dd \times d recurrent matrix and a d×nd \times n input matrix), where dd is hidden size and nn is input size. So each step costs O(d2+dn)O(d^2 + dn), and a full sequence of length TT costs O(T(d2+dn))O(T(d^2+dn)). A GRU has three affine transforms instead of four, so it is a constant factor (≈3/4\approx 3/4) cheaper per step but the same asymptotic order. Both match vanilla RNNs in asymptotic time complexity — the constant factor (3× or 4× more matrix multiplies) is the real cost of gating, not a complexity-class change.

Space complexity. Per-step memory is O(d)O(d) for the hidden state (plus O(d)O(d) for the cell state in LSTM); storing all intermediate activations for backpropagation through time costs O(Td)O(Td), since every gate/candidate value at every timestep must be cached for the backward pass. Parameter count is O(d2+dn)O(d^2+dn) for GRU and 43\frac{4}{3} times that for LSTM, independent of TT.

Correctness of the gradient-flow fix — the key argument. Consider the cell-state recurrence ct=ft⊙ct−1+it⊙c~tc_t = f_t \odot c_{t-1} + i_t \odot \tilde c_t. The partial derivative of ctc_t with respect to ct−1c_{t-1}, holding gates fixed, is:

∂ct∂ct−1=diag⁡(ft).\frac{\partial c_t}{\partial c_{t-1}} = \operatorname{diag}(f_t).

Compare this to the vanilla RNN's ∂ht/∂ht−1=diag⁡(tanh⁡′(⋅))Wh\partial h_t/\partial h_{t-1} = \operatorname{diag}(\tanh'(\cdot)) W_h, which involves the same shared matrix WhW_h at every step — its eigenvalues, raised to the kk-th power over kk steps, dictate exponential growth or decay independent of what the task needs. In contrast diag⁡(ft)\operatorname{diag}(f_t) involves no matrix multiplication at all, just an elementwise gate that the network learns per-dimension, per-timestep. If the network sets ft≈1f_t \approx \mathbf 1 (learned, e.g., by biasing bfb_f to be large and positive at initialization — a well-known practical trick), then

∂cT∂ct=∏s=t+1Tdiag⁡(fs)≈diag⁡(1)=I,\frac{\partial c_T}{\partial c_{t}} = \prod_{s=t+1}^{T} \operatorname{diag}(f_s) \approx \operatorname{diag}(\mathbf 1) = I,

so gradients backpropagate through the cell-state path across arbitrarily many steps without forced exponential decay. This is not a guarantee that gradients never vanish (if the task genuinely requires ft≪1f_t \ll 1 at some step, that path should attenuate), but it removes the structural obstruction that plagued vanilla RNNs: the network now has the freedom, via learnable gates, to choose long memory when the task demands it. The same reasoning applies to the GRU's ht=(1−zt)⊙ht−1+zt⊙h~th_t = (1-z_t)\odot h_{t-1} + z_t \odot \tilde h_t, where ∂ht/∂ht−1\partial h_t/\partial h_{t-1} has a diag⁡(1−zt)\operatorname{diag}(1-z_t) term along the direct path.

Tradeoffs. Gating does not eliminate vanishing gradients in the output gate / hidden-state path (LSTM's hth_t still passes through tanh⁡\tanh and gate multiplications every step), and very long sequences (thousands of steps) can still be difficult. LSTMs have more parameters and compute than GRUs for the same hidden size, which matters at scale; GRUs sometimes underperform LSTMs on tasks needing finer memory control (e.g., counting tasks benefit from LSTM's independent output gate). Both remain strictly sequential across time — step tt needs ht−1h_{t-1} — so they cannot be parallelized across the sequence dimension the way transformer self-attention can, which is the main reason they were later superseded in large-scale settings.

Worked example

Consider a toy LSTM with hidden size d=2d=2, scalar input n=1n=1, tracking whether a running total of a stream of numbers has ever exceeded a threshold (a task requiring long memory: the "exceeded" fact must persist regardless of later inputs). Suppose after training, the relevant gate weights approximately realize: forget gate saturates near 11 once the flag dimension is set (protecting the memory), input gate opens briefly at the triggering timestep, then closes. Trace with hand-picked (simplified, illustrative) parameter values, hidden dimension 1 (the "flag" unit), input xtx_t = the stream value, threshold behavior baked into weights:

ttxtx_tftf_titi_tc~t\tilde c_tct=ftct−1+itc~tc_t = f_t c_{t-1} + i_t \tilde c_toto_tht=ottanh⁡(ct)h_t = o_t\tanh(c_t)
0––––c0=0.00c_0 = 0.00–h0=0.00h_0 = 0.00
10.20.950.100.300.95(0)+0.10(0.30)=0.0300.95(0)+0.10(0.30)=0.0300.50.5tanh⁡(0.03)=0.0150.5\tanh(0.03)=0.015
20.90.900.850.950.90(0.03)+0.85(0.95)=0.8340.90(0.03)+0.85(0.95)=0.8340.60.6tanh⁡(0.834)=0.3830.6\tanh(0.834)=0.383
30.10.980.050.100.98(0.834)+0.05(0.10)=0.8220.98(0.834)+0.05(0.10)=0.8220.90.9tanh⁡(0.822)=0.5930.9\tanh(0.822)=0.593
40.00.990.020.000.99(0.822)+0.02(0)=0.8140.99(0.822)+0.02(0)=0.8140.950.95tanh⁡(0.814)=0.6340.95\tanh(0.814)=0.634

Read the trace as a story: at t=2t=2 the input crosses the threshold, the input gate opens (i2=0.85i_2=0.85) and lets a large candidate value (c~2=0.95\tilde c_2 = 0.95) into the cell state, jumping ctc_t from near 00 to 0.8340.834. From t=3t=3 onward, even though the raw inputs drop back to small values, the forget gate stays close to 1 (0.98,0.990.98, 0.99), so the cell state is barely eroded (0.834→0.822→0.8140.834 \to 0.822 \to 0.814) — the network has "remembered" that the threshold was crossed. The output gate oto_t grows over time, gradually exposing more of this memory into hth_t, which a downstream classifier reads to answer "has the threshold ever been exceeded?" A vanilla RNN attempting the same task would have to re-encode this fact through a tanh⁡\tanh-squashed matrix multiply at every single step, and — because tanh⁡′(⋅)≤1\tanh'(\cdot) \le 1 always — that signal would erode multiplicatively rather than being protected by a near-1 gate. For a gradient-flow comparison, suppose over 20 further steps the forget gate averages fˉ=0.98\bar f = 0.98 per dimension. The surviving fraction of the gradient signal reaching back 20 steps along the pure cell-state path is approximately fˉ20=0.9820≈0.667\bar f^{20} = 0.98^{20} \approx 0.667 — a mild, controllable attenuation. Contrast this with a vanilla RNN where the effective per-step contraction factor is often empirically well below 0.50.5 (products of tanh⁡′\tanh' terms near saturated regions and shrinking singular values), giving 0.520≈9.5×10−70.5^{20} \approx 9.5\times 10^{-7} — six orders of magnitude smaller. That gap is the entire practical payoff of gating.

Common pitfalls & traps

PitfallWhy it happensFix
Forgetting to initialize forget-gate bias positivelyDefault zero-init biases make ft≈0.5f_t \approx 0.5 initially, causing early training to forget too aggressivelyInitialize bfb_f to a positive value (e.g., 1–2) so gates start near "remember"
Confusing cell state ctc_t with hidden state hth_tOnly hth_t is typically fed to the output layer / next stacked layer, but both must be carried across timestepsAlways propagate the tuple (ht,ct)(h_t, c_t) for LSTM, not just hth_t
Assuming GRU is strictly better because it's "simpler"GRU merges cell/hidden state, which is a genuine capacity reductionBenchmark both; LSTM often wins for tasks needing separate read/write/forget control
Applying gradient clipping only to LSTM/GRU and skipping itPeople assume gating eliminates the need for clipping entirelyStill clip gradients — exploding gradients through tanh⁡\tanh candidate paths and stacked layers remain possible
Truncating BPTT too aggressivelyTruncation limits the very long-range dependencies gating was meant to enableChoose truncation length relative to the actual dependency span in the task, not just for compute convenience
Treating gate outputs as interpretable "on/off" switches literallyGates are continuous in (0,1)(0,1) and jointly learned; single dimensions rarely have clean semanticsUse ablations/probing rather than assuming a gate value alone explains model behavior

Pioneers & history

The LSTM was invented to directly solve the vanishing gradient problem that had been formally analyzed for recurrent networks in the early 1990s. Its constant-error-carousel idea — a self-loop with weight 1 acting as an uninterrupted gradient highway — was the conceptual seed for the additive cell-state update used today. The GRU emerged nearly two decades later as a leaner alternative designed for the same purpose but with a smaller parameter budget, becoming popular during the era of encoder-decoder machine translation systems.

Origins · 1 minSepp Hochreiter and how this was discovered
SH
Sepp Hochreiter
born 1967 · Developed the LSTM architecture with Jürgen Schmidhuber, directly motivated by his 1991 diploma thesis analysis of vanishing gradients in recurrent networks

History
1991
— Hochreiter's thesis formally characterizes the vanishing gradient problem in deep and recurrent networks.
1997
— Hochreiter and Schmidhuber publish "Long Short-Term Memory," introducing the constant error carousel and gated cell state.
2000
— Gers, Schmidhuber, and Cummins add the forget gate, completing the now-standard LSTM formulation.
2014
— Cho et al. introduce the Gated Recurrent Unit for neural machine translation encoder-decoder models.
2014–2015
— LSTM/GRU-based sequence-to-sequence models become the dominant architecture for translation, speech, and captioning.

Where this matters

Gated recurrent architectures powered production systems for roughly a decade: Google's neural machine translation system (pre-transformer) used stacked LSTMs; Apple's Siri and various speech-recognition pipelines used LSTM acoustic models; handwriting recognition, music generation, and time-series forecasting systems widely adopted LSTM/GRU cells. They remain a strong choice today for streaming or low-latency inference (constant per-step compute, no need to attend over a growing context window), for small-to-medium datasets where transformers' data hunger is a liability, and as building blocks inside larger systems such as Encoder-Decoder Architectures used in translation and summarization before attention mechanisms took over that role. Understanding gating is also essential background for appreciating why attention and transformers were adopted — attention solves the sequential-bottleneck and long-range-dependency problems that gating only partially addressed, without the sequential O(T)O(T) dependency chain that limits Recurrent Neural Networks parallelism.

Ask the tutor: Can you derive, step by step, how the LSTM's forget-gate gradient path compares numerically to a vanilla RNN's gradient decay over 50 timesteps?

Why do vanilla RNNs suffer from vanishing gradients but LSTMs mitigate it?

In a vanilla RNN, the gradient of the loss with respect to an early hidden state is a product of many Jacobians, each roughly diag⁡(tanh⁡′)Wh\operatorname{diag}(\tanh') W_h. Since ∣tanh⁡′∣≤1|\tanh'|\le 1 and repeated multiplication by the same matrix WhW_h tends to shrink or grow singular values geometrically, the gradient magnitude scales like λk\lambda^k over kk steps, vanishing for λ<1\lambda<1. The LSTM instead updates its cell state additively, ct=ft⊙ct−1+it⊙c~tc_t = f_t \odot c_{t-1} + i_t \odot \tilde c_t, so ∂ct/∂ct−1=diag⁡(ft)\partial c_t/\partial c_{t-1} = \operatorname{diag}(f_t) involves no matrix multiplication. If the network learns ft≈1f_t \approx 1 for dimensions it must remember, gradients pass through nearly unchanged across many steps, removing the structural cause of vanishing.

Is a GRU strictly simpler and worse than an LSTM, or just different?

A GRU is more parameter-efficient (three gates and one state vector versus four gates and two state vectors), which speeds up training and reduces overfitting risk on smaller datasets. It is not strictly worse: many empirical studies find GRUs match or slightly exceed LSTM performance on tasks like language modeling and machine translation, especially with limited data. LSTMs tend to have an edge on tasks needing very fine-grained memory control, such as counting or tracking multiple independent quantities, because the input, forget, and output decisions are decoupled rather than tied together through a single update gate. The right choice is empirical, not automatic.

What exactly does the cell state store, conceptually?

The cell state ctc_t is a vector of "memory slots," each dimension independently protected or overwritten by the forget and input gates. Unlike the hidden state hth_t, which is squashed through tanh⁡\tanh and gated by oto_t before being exposed to the rest of the network, the cell state is only ever combined additively across timesteps and is never directly consumed by downstream layers. This separation lets the network preserve raw, unsquashed information across long spans while still producing a bounded, filtered output (hth_t) at each step for use by the next layer or the loss function.

Do LSTMs and GRUs completely solve the vanishing gradient problem?

No — they substantially mitigate it along the additive memory path but do not eliminate it everywhere. The hidden-state path in an LSTM still passes through tanh⁡\tanh and gate multiplications at every step, so gradients along that path can still shrink. If a task genuinely requires forgetting (small ftf_t), the corresponding gradient path is correctly attenuated, which is desired behavior, not a bug. In practice, extremely long sequences (thousands of steps) can still pose difficulties, and techniques like gradient clipping, careful initialization, and truncated backpropagation through time remain standard companions to gated architectures.

How do LSTMs and GRUs relate to attention and transformers?

LSTMs and GRUs process sequences step by step, so the model at time TT can only access earlier information indirectly, compressed through the recurrent state, and computation cannot parallelize across the time dimension. Attention mechanisms, central to transformer architectures, let every position directly attend to every other position in a single parallelizable operation, sidestepping both the sequential bottleneck and much of the long-range decay issue. Historically, attention was first added on top of LSTM-based encoder-decoder models to help with long sequences, and only later did architectures drop the recurrence entirely in favor of pure attention, which is the lineage into Encoder-Decoder Architectures and transformers.

Why does the forget gate use a sigmoid instead of a tanh or ReLU?

Gates need to act as soft, per-dimension switches whose output represents "how much of this quantity to keep," which requires a bounded range of [0,1][0,1]: a sigmoid naturally produces this range, with 0 meaning "fully forget" and 1 meaning "fully retain." A tanh⁡\tanh output in [−1,1][-1,1] would allow sign flips that don't correspond to a sensible gating semantic, and ReLU is unbounded above and cannot represent "keep half" or "discard entirely" in a bounded, smooth, differentiable way. The candidate content c~t\tilde c_t, by contrast, uses tanh⁡\tanh precisely because it represents actual values to be blended in, not a gating decision.

What practical tricks improve LSTM/GRU training beyond the architecture itself?

Initialize the forget-gate bias to a positive value (commonly 1) so the network starts by retaining information rather than erasing it. Apply gradient clipping (by norm, typically to a threshold like 1–5) since exploding gradients remain possible through stacked layers or the candidate/output paths. Use orthogonal initialization for recurrent weight matrices to keep their spectral radius near 1 at the start of training. Consider layer normalization inside the cell for very deep stacks, and always monitor gate activations during training — gates saturating near 0 or 1 everywhere for all inputs is a sign of a training pathology, not learned structure.

Before this

Where this leads