Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 6

Adam Optimizer: Adaptive Learning Rates

Recommended resources

Hello! Welcome to the sixth lesson in our module on Neural Network Foundations.

In our last lesson, we saw how momentum helps accelerate training by smoothing out the noisy updates of SGD. By accumulating velocity, it dampens oscillations in narrow ravines and builds speed in consistent downhill directions. However, we were still using a single, fixed learning rate for all parameters in our network.

This brings us to a key question: should every parameter learn at the same rate? In complex loss landscapes, some parameters might be in flat regions needing large updates, while others are in steep valleys requiring small, careful steps.

Today, we will address this by exploring the Adam optimizer. The learning outcome for this lesson is to implement the Adam optimizer and explain its adaptive learning rate mechanism. Adam, which stands for Adaptive Moment Estimation, is arguably the most popular and effective optimization algorithm for deep learning today. It cleverly combines the momentum concept with per-parameter adaptive learning rates, making it both fast and robust.

1. From Momentum to Adaptive Learning Rates

Let's quickly recap. Momentum tracks an exponentially weighted moving average of the gradients, which we can call the first moment. This helps determine the direction of our update.

Adam keeps this idea but adds a second, crucial component: an exponentially weighted moving average of the squared gradients, known as the second moment. This will help control the magnitude of our update for each parameter individually.

The intuition is as follows:

  • If a parameter's gradients are consistently large, its second moment estimate will be large.
  • If a parameter's gradients are small or sparse, its second moment estimate will be small.

Adam uses this second moment to scale the learning rate for each parameter. Specifically, it divides the update by the square root of . This means parameters with large historical gradients will get smaller updates (to prevent overshooting), and parameters with small gradients will get larger updates (to make progress). This is the essence of its adaptive learning rate mechanism.

To see how these ideas from Momentum and another optimizer, RMSprop, are combined, let's watch a brief introductory video.

Adam Optimizer from Scratch in Python

The video 'Adam Optimizer from Scratch in Python' by Yacine gives a great high-level overview of where Adam comes from, framing it as a combination of Momentum and RMSprop.

Watch the first segment (00:00 to 01:47) to understand Adam's context and its connection to its predecessors. Then, watch the summary segment (14:27 to 15:16) which recaps how SGD, Momentum, and per-parameter scaling all come together in Adam.


2. The Adam Algorithm: A Step-by-Step Breakdown

Adam is more than just smashing momentum and adaptive rates together. It includes a critical refinement called bias correction. Let's walk through the full algorithm. The Vizuara channel provides an excellent and clear walkthrough of the math and implementation.

Adam Optimizer from scratch | Gradient descent made better | Foundations for ML [Lecture 26]

The video 'Adam Optimizer from scratch' will be our main guide. It breaks down each mathematical step and then translates it directly into Python code.

Please watch from 01:05 to 17:25. This covers: A quick recap of gradient descent, momentum, and RMSprop. The core steps of Adam: calculating the first and second moments. The crucial concept of bias correction and why it's needed. The final parameter update rule that combines everything.

Let's formalize the steps from the video. At each training step , for each parameter:

  1. Compute Gradient: Calculate the gradient .
  2. Update First Moment (Momentum): This is the momentum term, tracking the mean of the gradients. is typically 0.9.
  3. Update Second Moment (Uncentered Variance): This tracks the variance of the gradients. is typically 0.999.
  4. Apply Bias Correction: Since and are initialized to zero, the estimates and are biased toward zero in the initial stages of training. We correct for this bias:
  5. Update Parameters: Finally, we update the parameters using the bias-corrected estimates: Here, is the main learning rate, and (e.g., ) is a small value to prevent division by zero.

The term acts as the effective, per-parameter learning rate.

For a more detailed derivation of the bias correction, which is a key theoretical contribution of Adam, the following article is an excellent resource.

Adam Optimizer: Adaptive Learning Rates for Neural Network ...

The article 'Adam Optimizer' from mbrenndoerfer.com provides a first-principles derivation of the entire algorithm. We'll focus on the section explaining the bias correction problem and its solution.

Read the sections 'The Bias Correction Problem' and 'The Adam Update Rule'. The first part gives a clear mathematical derivation for the correction terms. The second part puts all the pieces together, which will reinforce what you saw in the video.

Test your understanding!

Imagine you are training a neural network for a Natural Language Processing (NLP) task. One of the parameters corresponds to a very rare word in your vocabulary. This parameter's gradient, , will be zero most of the time and non-zero only occasionally.

How does Adam's adaptive mechanism help this parameter learn effectively compared to standard SGD or Momentum?

Show answer

For this parameter:

  1. The squared gradient will also be zero most of the time.
  2. Therefore, the second moment estimate, , which is a moving average of , will be a very small number.
  3. In the final update rule, , the denominator will be very small.
  4. This results in a large effective learning rate for this parameter whenever its gradient is non-zero. Adam essentially "boosts" the learning for infrequent parameters, allowing them to catch up. In contrast, SGD or Momentum would apply the same small, global learning rate, and the parameter might never be updated meaningfully.

3. Implementing Adam from Scratch

Now let's translate the algorithm into code. Your background in Python and previous projects will make this process familiar. We will implement a function that performs the Adam update rule.

The video you watched earlier contains a complete, from-scratch implementation. Additionally, the Machine Learning Mastery article provides a very readable, step-by-step coding guide.

Code Adam Optimization Algorithm From Scratch

To reinforce the implementation details, let's review the 'Code Adam Optimization Algorithm From Scratch' article. It uses an imperative style that clearly shows each step of the calculation within the loop.

Focus on the section 'Gradient Descent Optimization With Adam'. Read through the code for the adam() function. Notice how it initializes m and v, and then inside the loop, it calculates the moments, applies bias correction, and finally updates the solution x.

Here is a consolidated Python implementation based on the resources. It performs Adam optimization on a simple quadratic objective function .

import numpy as np
import matplotlib.pyplot as plt

# Objective function and its derivative
def objective(x, y):
    return x**2.0 + y**2.0

def derivative(x, y):
    return np.array([x * 2.0, y * 2.0])

# Adam optimizer function
def adam(objective_fn, derivative_fn, bounds, n_iter, alpha, beta1, beta2, eps=1e-8):
    # Start at a random point within the bounds
    solution = bounds[:, 0] + np.random.rand(len(bounds)) * (bounds[:, 1] - bounds[:, 0])
    
    # Initialize first and second moment vectors
    m = np.zeros(len(bounds))
    v = np.zeros(len(bounds))
    
    path = [solution.copy()]
    for t in range(1, n_iter + 1):
        # 1. Compute gradient
        g = derivative_fn(solution[0], solution[1])
        
        # 2. Update first moment estimate
        m = beta1 * m + (1.0 - beta1) * g
        
        # 3. Update second moment estimate
        v = beta2 * v + (1.0 - beta2) * g**2
        
        # 4. Compute bias-corrected estimates
        m_hat = m / (1.0 - beta1**t)
        v_hat = v / (1.0 - beta2**t)
        
        # 5. Update parameters
        solution -= alpha * m_hat / (np.sqrt(v_hat) + eps)
        
        path.append(solution.copy())
        
    return path

# --- Hyperparameters ---
bounds = np.asarray([[-1.0, 1.0], [-1.0, 1.0]])
n_iter = 100
alpha = 0.02
beta1 = 0.8
beta2 = 0.999

# --- Run and Plot ---
path_adam = adam(objective, derivative, bounds, n_iter, alpha, beta1, beta2)
path_adam = np.array(path_adam)

# You can run this code locally to visualize the optimization path
# The path will show a much more direct and rapid convergence than simple SGD
print(f"Adam finished. Final point: {path_adam[-1]}")

Notice how each line in the loop directly maps to the five steps of the algorithm we defined. This small amount of code encapsulates a powerful optimization strategy that is the backbone of training for many modern neural networks.


4. Why is Adam so Widely Used?

Adam's combination of momentum and adaptive learning rates makes it incredibly effective and robust.

Comparison of Adam to Other Optimization Algorithms
This graph compares the training cost reduction for several popular optimizers on the MNIST dataset. The Adam optimizer (magenta line) converges significantly faster and to a lower cost than the others, demonstrating its efficiency.

The key benefits are:

  • Fast Convergence: It often finds the minimum of the loss function much faster than other optimizers.
  • Robustness: It is less sensitive to the choice of the learning rate () than SGD. The default hyperparameters () work well for a surprisingly wide range of models.
  • Memory Efficiency: It requires little memory, as it only needs to store the first and second moment vectors, which are the same size as the parameter gradients.

Conclusion

Congratulations! You have now mastered one of the most important algorithms for training deep neural networks. By understanding how Adam works from first principles and implementing it yourself, you have gained a deep insight that goes far beyond simply calling a library function.

Key Takeaways:

  • Core Idea: Adam combines momentum (first moment of gradients) to determine update direction with an adaptive learning rate mechanism (second moment of gradients) to scale the update magnitude for each parameter.
  • Adaptive Mechanism: It divides the learning rate by a moving average of squared gradients (). This gives smaller updates to parameters with large, consistent gradients and larger updates to those with small or sparse gradients.
  • Bias Correction: Adam corrects for the initial zero-bias of its moment estimates, making it reliable from the very first training steps.
  • Implementation: The algorithm involves five steps: compute gradient, update first moment, update second moment, apply bias correction, and update parameters.

Preview of the Next Lesson:
So far, we have focused entirely on making our model train faster and more effectively. But what if our model gets too good at learning the training data? It might start to memorize the examples, including their noise, and fail to perform well on new, unseen data. This problem is called overfitting.

In our next lesson, we will begin tackling this issue by exploring our first regularization technique. You will implement dropout regularization and explain how it prevents overfitting by randomly "turning off" neurons during training, forcing the network to learn more robust features.