Learning Rate Adjustment in Training Loops
Linear warmup gradually increases the learning rate from initial_lr to peak_lr during the first warmup_steps batches of training.
A Learning Rate That Moves Each Step
A learning rate controls how large a change the optimizer makes to a model's weights on each update. In many simple training loops it stays at one value for the entire run. The training function in this article does something different: it recalculates the learning rate on every step of the loop, and it uses one rule for the early steps and another rule for the rest of training. The two rules are called the warmup phase and the cosine annealing phase. Warmup is the first of these phases and is the focus of this article.
What do you think happens?
The warmup branch raises the learning rate from a starting value toward a peak value over a fixed number of steps. From one step to the next, what do you think happens to the learning rate?
Reveal answer
It rises by the same amount on every step.
The word linear describes the shape of the change. The learning rate rises by a fixed increment on every step, so plotted against steps it forms a straight line.
As you read the training function, keep one question in mind: at a given step of training, which rule decides the learning rate, and why? The rest of this article follows that question from the warmup formula, to the point where the rule changes, to the line of code that sets the value the optimizer uses.
Linear Warmup as a Straight-Line Ramp
Linear warmup gradually increases the learning rate from initial_lr to peak_lr during the first warmup_steps batches of training. The word linear describes the shape of the change: the learning rate rises by the same amount on every step, so plotted against steps it forms a straight line. The source describes this increment as a fixed quantity computed once, before the training loop begins.
During warmup, the learning rate at each step is the initial value plus the number of steps taken so far, multiplied by the increment. The source writes this as lr = initial_lr + global_step * lr_increment, where global_step is the step counter.
In these formulas, I stands for initial_lr, P stands for peak_lr, W stands for warmup_steps, s stands for global_step, and Delta stands for lr_increment. The first formula is the increment, computed once. The second formula gives the learning rate on each warmup step.
The diagram uses the example values initial_lr = 0.0001, peak_lr = 0.001, and warmup_steps = 5. Each step adds the same amount, so the points lie on a straight line from the starting value to the peak. Each step label shows the learning rate at that step.
Computing the Warmup Increment by Hand
Finding the increment and the first warmup rates
Given initial_lr = 0.0001, peak_lr = 0.001, and warmup_steps = 5, find lr_increment and the learning rate at global_step = 0, 1, 2, 3, and 4.
- 1Compute the difference between peak and initial values
peak_lrminusinitial_lris 0.001 minus 0.0001, which equals 0.0009. - 2Divide by warmup_steps to get lr_increment
0.0009 divided by 5 equals 0.00018. This is the amount the learning rate rises on every warmup step.
- 3Apply the warmup formula at each step
The rate is
initial_lrplusglobal_steptimeslr_increment. Atglobal_step= 0 it is 0.0001. Atglobal_step= 1 it is 0.0001 plus 0.00018, which equals 0.00028. Atglobal_step= 2 it is 0.00046, atglobal_step= 3 it is 0.00064, and atglobal_step= 4 it is 0.00082. - 4Check the value that would appear at warmup_steps
At
global_step= 5 the linear formula would give 0.0001 plus 5 times 0.00018, which equals 0.001, the peak. The warmup conditionglobal_step<warmup_stepsis now false, so this step is handled by the cosine branch instead.
lr_increment is 0.00018. The warmup rates for global_step 0 through 4 are 0.0001, 0.00028, 0.00046, 0.00064, and 0.00082. Step 5 is no longer in the warmup phase.
0 0.0001
1 0.00028
2 0.00046
3 0.00064
4 0.00082lr_incrementis computed from the three inputs, the same way the source describes it- The return line is the warmup formula,
initial_lrplusglobal_steptimeslr_increment - round is used only to make the printed values easy to read
Where the Peak Rate Comes From
The training function takes initial_lr and min_lr as arguments, with default values in the function signature. It does not receive a peak learning rate as an argument. Instead, it reads the peak from the optimizer, using the learning rate stored in the optimizer's first parameter group. The source notes that this assumes the optimizer's starting learning rate is used as the peak learning rate.
initial_lrandmin_lrare arguments with default valuespeak_lris not an argument; it is read from the first parameter group of the optimizertotal_training_stepsis the loader length multiplied by the number of epochs
The function also calculates total_training_steps as the length of the training loader multiplied by the number of epochs. The warmup_steps value is the number that controls how long the ramp lasts. The code sample above is an illustration written for this article to show where each value comes from; the names match the source, but the default values and the warmup_steps line are example choices.
How the Loop Chooses a Phase Each Batch
The learning rate itself is recalculated inside the innermost loop, once per batch, because the step counter changes once per batch. On each pass, the code first checks the condition global_step < warmup_steps. When that condition is true, the code uses the linear formula. When it is false, the code uses the cosine formula.
The flowchart shows the decision that runs on every batch. The check is made against the current value of global_step, so the chosen branch can change from one batch to the next without any other change to the code.
Switching to Cosine Annealing
Once global_step reaches warmup_steps, the training function stops using the linear rule and starts using cosine annealing. Cosine annealing is a technique used to adjust the learning rate after the warmup phase. The two phases share the same step counter and the same peak_lr. Warmup climbs toward the peak, and cosine annealing starts from that peak and decreases toward the minimum.
The variable progress measures how far training has moved through the post-warmup period. The source defines it as the number of steps completed after warmup, divided by the number of steps remaining after warmup. The number of steps remaining is the total number of training steps minus warmup_steps. Because progress is measured from the end of warmup, the cosine schedule begins from the peak learning rate and moves toward min_lr as training continues.
Mistakes That Produce Wrong Rates
Most unexpected learning rate values come from a small set of misreadings. The items below are the ones most likely to send you looking in the wrong place.
Common mistake Assuming the warmup branch runs on the step where global_step equals warmup_steps
What it looks likeWith warmup_steps = 5, a learner expects step 5 to still use the linear formula.
Why it failsThe warmup branch begins with the condition
global_step<warmup_steps. Atglobal_step= 5 that condition is false, so the cosine formula applies.Do this insteadCheck the strict less-than comparison. The last warmup step is warmup_steps minus 1.
Common mistake Looking for peak_lr among the function arguments
What it looks likeA learner searches the function signature for a peak_lr parameter and cannot find one.
Why it failsThe function takes
initial_lrandmin_lras arguments. The peak is read from the optimizer's first parameter group.Do this insteadTrace peak_lr back to the optimizer's first parameter group.
Common mistake Recomputing the increment inside the batch loop
Why it failsThe source says the increment is computed once, before the epoch loop starts. Only the step counter and the resulting learning rate change per batch.
Do this insteadLook for lr_increment being set once, above the epoch loop.
Common mistake Thinking the learning rate stays constant during the whole run
Tracing an Unexpected Learning Rate Value
When a learning rate looks wrong during training, the fastest path to the cause is to ask three questions in order. Each question points to one line of the training function, so the divergence can be located rather than guessed.
- 1First, identify which branch applied at that step: was
global_stepbelowwarmup_steps? - 2Second, for a warmup step, check the values of
initial_lr,peak_lr, andwarmup_stepsthat fed intolr_increment. - 3Third, for a cosine step, check
total_training_stepsandwarmup_steps, since those define progress.
Practicing a Warmup Trace
Using the warmup_lr function from the earlier example, with initial_lr = 0.0001, peak_lr = 0.002, and warmup_steps = 4, what is lr_increment, and what learning rate does the warmup formula give at global_step = 2? Also state which branch the training loop uses at global_step = 4.
Hints
- Subtract
initial_lrfrompeak_lrfirst, then divide bywarmup_steps. - At
global_step= 2, multiplylr_incrementby 2 and addinitial_lr. - The warmup condition is
global_step<warmup_steps, so compare 4 with 4.
Key Takeaways
- Linear warmup raises the learning rate by a fixed increment on each step during the first
warmup_stepsbatches, forming a straight line frominitial_lrtopeak_lr. lr_incrementequals (peak_lr-initial_lr) divided bywarmup_steps, and it is computed once before the epoch loop. The warmup rate at each step isinitial_lrplusglobal_steptimeslr_increment.- The training loop checks
global_step<warmup_stepson every batch. Once that condition is false, the cosine annealing phase takes over, starting from the peak and moving towardmin_lr. peak_lris read from the optimizer's first parameter group, not passed as an argument, so an unexpected value can be traced to that source or to the increment line.- When a rate looks wrong, identify the phase first, then check the inputs that feed that phase's formula.