A theoretically improved Adam optimizer

AdamW is very similar to Adam. It only differs in the way how the weight decay is implemented. The way how it's implemented in Adam came from the good old vanilla SGD optimizers which isn't mathematically correct. AdamW fixes this implementation mistake.

The authors of the original AdamW paper claimed that they were able to solve the generalization issues of the Adam solver with their modification. Empirically speaking, however, it seems that the right hyperparameter settings have a bigger impact than the choice between Adam and AdamW, but AdamW generalizes a bit better.

Code implementation

import torch
# N is batch size; D_in is input dimension;
# H is hidden dimension; D_out is output dimension.
N, D_in, H, D_out = 64, 1000, 100, 10
# Create random Tensors to hold inputs and outputs.
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
# Use the nn package to define our model and loss function.
model = torch.nn.Sequential(
torch.nn.Linear(D_in, H),
torch.nn.Linear(H, D_out),
loss_fn = torch.nn.MSELoss(reduction='sum')
# Use the optim package to define an Optimizer that will update the weights of
# the model for us. Here we will use AdamW; the optim package contains many other
# optimization algorithms. The first argument to the Adam constructor tells the
# optimizer which Tensors it should update.
learning_rate = 1e-4
optimizer = torch.optim.AdamW(model.parameters(), lr=learning_rate, weight_decay=0.01, amsgrad=False)
for t in range(500):
# Forward pass: compute predicted y by passing x to the model.
y_pred = model(x)
# Compute and print loss.
loss = loss_fn(y_pred, y)
print(t, loss.item())
# Before the backward pass, use the optimizer object to zero all of the
# gradients for the Tensors it will update (which are the learnable weights
# of the model)
# Backward pass: compute gradient of the loss with respect to model parameters
# Calling the step function on an Optimizer makes an update to its parameters
# TensorFlow Addons is a repository of contributions that conform to well- established API patterns
# But implement new functionality not available in core TensorFlow.
!pip install tensorflow-addons
# importing the library
import tensorflow as tf
import tensorflow_addons as tfa
opt = tfa.optimizers.AdamW(learning_rate=0.1,weight_decay=0.01, amsgrad=False)
var1 = tf.Variable(10.0)
loss = lambda: (var1 ** 2)/2.0 # d(loss)/d(var1) == var1
step_count = opt.minimize(loss, [var1]).numpy()

Further resources