Remembering the Direction of Earlier Updates
Successive batches can pull a weight in different directions. A stored velocity lets Botie carry some of the previous update direction into the next step.
13 sections · 4 questions · 2 coding challenges
The arrow keys move between sections too.
Keeping Useful Direction Across Steps
BOTIE
There are several conventions for scaling the stored state. Here velocity equals beta times the old velocity plus the current gradient; the learning rate is applied when changing the parameter.
Sources for this history
Why Does the Weight Keep Moving Back and Forth?
One batch tells Botie to increase a weight, while the next tells him to decrease it. Some of that variation comes from sampling, and some comes from the shape of the loss.
Could the recent gradients help us decide which way to move? Momentum keeps a velocity between updates and combines it with the current gradient. We need to track that velocity separately from the parameter: a parameter can keep moving in its previous direction even after the latest gradient changes sign.
The supplied gradients isolate the momentum update from a full training run.
Step 1 of 3
Remember the previous gradient direction
Velocity is separate from the parameter.
Previous velocity: 2 Current gradient: −1
Step 2 of 3
Retain part of that direction
A retention factor controls the old contribution.
Retained fraction beta: 0.5 New velocity = (0.5 × 2) + (−1) = 0
Step 3 of 3
Update using velocity
Opposing contributions can cancel for this step.
Old weight: 4 New weight = 4 − (learning rate × 0) = 4
Velocity carries earlier gradients into the next update
Velocity combines old and new direction before scaling the parameter change.
Does the next update remember the previous direction?
Try a gradient that agrees with the stored velocity, then one that opposes it. Compare the resulting parameter movement before discarding that history.
BOTIE
Parameter value after the momentum update
4
Follow the operations
1. Weight
4
2. Learning rate
0.1
3. Retention
0.5
4. Old velocity
2
5. Multiply
1
6. Current gradient
-1
7. Add
0
8. Multiply
0
9. Subtract
4
10. Result
4
This uses v_new = beta*v + gradient, with beta in [0,1).
1. Add a State Variable With a Clear Job
A plain descent step uses only the current gradient. Momentum also stores velocity, usually initialised to zero. The retention factor beta determines how much old velocity survives.
Velocity has the same shape as the parameter array. It must persist between batches, rather than be recreated inside each update. Keeping a state for the wrong parameter shape can silently mix unrelated quantities.
Momentum needs more state than the weights alone.
2. Calculate Velocity Before the Weight
Multiply old velocity by beta and add the new gradient. Then subtract the learning-rate-scaled velocity from the weight. In this convention, we do not multiply the current gradient by one minus beta.
Old velocity = 2; beta = 0.5; gradient = -1
New velocity = 0.5 × 2 - 1 = 0
New weight = 4 - 0.1 × 0 = 4Other conventions are valid, but their learning rates and stored values are not interchangeable.
3. Follow More Than One Step
With repeated gradients in one direction, velocity grows until decay balances the incoming contribution. When a gradient reverses, old velocity can delay the reversal of the parameter’s motion.
That memory can help in narrow loss valleys, but can also carry an update past a minimum. Momentum does not know where the minimum is; it only combines gradients.
Plot the parameter and velocity separately when debugging a training run.
An agreeing gradient adds to the stored direction
The old velocity is positive and the new gradient agrees with it. Retain half the old velocity, add the current gradient, and only then scale the parameter movement.
import numpy as np
weight = 4.0
old_velocity = 2.0
gradient = 1.0
retention, rate = 0.5, 0.1
velocity = retention * old_velocity + gradient
print(velocity)
print(weight - rate * velocity)2.0
3.8Velocity and learning rate have different jobs. The challenge carries the updated velocity into a second step where the gradient changes direction.
4. Save Optimiser State When Resuming
Restarting with the same weights but zero velocity changes the next update. For a faithful continuation, save the optimiser state, update count, learning-rate schedule, and relevant random state.
Compare momentum settings on a validation procedure. A high retention factor is not always better, and changing it changes the scale of accumulated velocity under this convention.
The workshop makes one velocity update, then uses it to change the weight.
5. Velocity Remembers Directions That Have Already Changed
Momentum carries part of the previous update direction into the next step. If gradients repeatedly point the same way, those contributions accumulate. If signs alternate, they can partly cancel.
That memory means the current update need not point along the current gradient alone. Near a minimum, old velocity can carry the parameter past it. A learning rate and momentum coefficient must therefore be considered together, rather than treating momentum as an automatic acceleration button.
6. Watch the Parameter after the Gradient Reverses
We will use a velocity that accumulates gradients, followed by subtracting learning rate times velocity. Another common convention includes learning rate inside the velocity. The two forms need consistent state definitions, especially if the learning rate changes.
Track gradient, velocity and parameter separately. Their signs answer different questions: current slope, retained direction and current location.
Three updates with one reversal
The first two gradients are positive and the third is negative.
import numpy as np
w, velocity = 0., 0.
for gradient in [2.,2.,-1.]:
velocity = .8*velocity + gradient
w -= .1*velocity
print(round(velocity, 3), round(w, 3))2.0 -0.2
3.6 -0.56
1.88 -0.748Even after the slope reverses, the retained velocity still moves the parameter in the previous direction. This is expected under the stated rule.
7. Resume the Optimiser, Not Only the Weights
A training checkpoint needs the velocity as well as the model parameters. Restoring only the weights and zeroing velocity starts a different trajectory, even on the same next batch.
Test checkpoint continuation against an uninterrupted run. Save the learning-rate schedule position and random state when they influence the next updates. If a run oscillates, inspect these states and gradient scales before adding more training passes.
Check yourself
Questions on Parts 1 to 7
Question 1 of 4
What is the new velocity?
Use the information below.
v=2, beta=0.5, g=-1; v_new=beta*v+g.Try it with Botie
Build with Botie
Write and run Python