In PyTorch, custom weight constraints or penalties can be implemented by making use of the regularization functionality of the PyTorch optimizer. Regularization techniques are designed to overcome the overfitting problem which occurs when a model is too closely fitted to the training data and thus doesn’t generalize well to new samples. Regularization techniques introduce additional constraints to the optimization process to prevent model overfitting. Weight regularization is one such technique which constrains the weights of the neural network to help reduce overfitting.
We have two types of regularization techniques in PyTorch: L1 and L2 regularization. In L1 regularization, the weights are constrained by the L1-norm, while in L2 regularization, the weights are constrained by the L2-norm.
Here’s an example of implementing L2 weight regularization in PyTorch:
import torch
import torch.nn as nn
import torch.optim as optim
from torch.autograd import Variable
# Define a custom weight regularization function
def l2_regularization(model, lambda_):
loss_reg = 0
for param in model.parameters():
loss_reg += torch.sum(param ** 2)
return 0.5 * lambda_ * loss_reg
# Define a simple neural network model
class Net(nn.Module):
def __init__(self, input_dim, output_dim, hidden_dim):
super(Net, self).__init__()
self.linear1 = nn.Linear(input_dim, hidden_dim)
self.linear2 = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
out = torch.relu(self.linear1(x))
out = self.linear2(out)
return out
# Initialize neural network model
input_dim = 10
hidden_dim = 20
output_dim = 1
model = Net(input_dim, output_dim, hidden_dim)
# Define loss function, optimizer and regularization hyperparameter
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.1)
lambda_ = 0.001
# Train the model for some epochs with L2 regularization
for epoch in range(5):
for i, data in enumerate(train_loader):
x, y = data
x, y = Variable(x), Variable(y)
# Forward pass
y_pred = model(x)
# L2 regularization
reg_loss = l2_regularization(model, lambda_)
# Compute loss
loss = criterion(y_pred.squeeze(), y) + reg_loss
# Backward pass and optimization
optimizer.zero_grad()
loss.backward()
optimizer.step()
In this example, we define a custom weight regularization function ‘l2_regularization‘ which takes as input the neural network model and the regularization hyperparameter ‘lambda_‘. The function computes the regularization loss based on the L2-norm of the weights.
We then define a simple neural network model ‘Net‘ and initialize it with some input and output dimensions as well as hidden dimension to add some complexity in our model. We also define our loss function (mean squared error) ‘criterion‘, optimizer (Adam) ‘optimizer‘ and the regularization hyperparameter ‘lambda_‘.
In the training loop, we forward pass the inputs, then calculate the loss which includes our custom L2 regularization function using the ‘l2_regularization‘ function. Finally, we compute gradients, backpropagate and update the parameters using the optimizer.
We can also implement L1 regularization in a similar way. The only difference is that we take the L1-norm of the weights instead of the L2-norm. The regularization function would be modified as follows:
def l1_regularization(model, lambda_):
loss_reg = 0
for param in model.parameters():
loss_reg += torch.sum(torch.abs(param))
return lambda_ * loss_reg
Similarly, we would modify the loss term in the training loop to include the L1 regularization term instead of the L2 regularization term.