import torch
import matplotlib.pyplot as plt
import torch.distributions as dist
import copy
from functools import partial
# Matplotlib retina
%config InlineBackend.figure_format = 'retina'
from sklearn.metrics import accuracy_score
import torch.nn.functional as F
import pandas as pd
import numpy as np
BayesOpt Motivation
# From: https://glowingpython.blogspot.com/2017/04/solving-two-spirals-problem-with-keras.html
def twospirals(n_points, noise=1.7):
"""
Returns the two spirals dataset.
"""
= np.sqrt(np.random.rand(n_points,1)) * 780 * (2*np.pi)/360
n = -np.cos(n)*n + np.random.rand(n_points,1) * noise
d1x = np.sin(n)*n + np.random.rand(n_points,1) * noise
d1y return (np.vstack((np.hstack((d1x,d1y)),np.hstack((-d1x,-d1y)))),
np.hstack((np.zeros(n_points),np.ones(n_points))))
= twospirals(1000)
X, y
0], X[:,1], c=y, cmap=plt.cm.Spectral) plt.scatter(X[:,
<matplotlib.collections.PathCollection at 0x7f382737a190>
# Divide the dataset into train, test and validation
from sklearn.model_selection import train_test_split
= train_test_split(X, y, random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X_train, y_train, random_state=0) X_train, X_val, y_train, y_val
X_train.shape, X_test.shape, X_val.shape
((1125, 2), (500, 2), (375, 2))
# Move to torch tensors
= torch.tensor(X_train, dtype=torch.float)
X_train = torch.tensor(y_train, dtype=torch.float)
y_train
= torch.tensor(X_test, dtype=torch.float)
X_test = torch.tensor(y_test, dtype=torch.float)
y_test
= torch.tensor(X_val, dtype=torch.float)
X_val = torch.tensor(y_val, dtype=torch.float) y_val
# Create a simple MLP with hyperparameter being the regularization strength
class SimpleMLP(torch.nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super(SimpleMLP, self).__init__()
self.fc1 = torch.nn.Linear(input_dim, hidden_dim)
self.fc2 = torch.nn.Linear(hidden_dim, hidden_dim)
self.fc3 = torch.nn.Linear(hidden_dim, output_dim)
def forward(self, x):
= torch.sin(self.fc1(x))
x = torch.sin(self.fc2(x))
x = self.fc3(x)
x return x
import torch.nn.functional as F
import torch.optim as optim
# Define a function to train and evaluate a model with a given regularization rate
def train_and_evaluate_model(lam):
= SimpleMLP(input_dim=2, hidden_dim=80, output_dim=1)
model = optim.Adam(model.parameters(), lr=0.001)
optimizer = torch.nn.BCEWithLogitsLoss()
criterion
= 500
epochs for epoch in range(epochs):
# Forward pass
= model(X_train)
outputs = criterion(outputs, y_train.unsqueeze(1))
loss
# L2 regularization
= torch.tensor(0.)
l2_reg for param in model.parameters():
+= torch.norm(param)
l2_reg
+= lam * l2_reg
loss
# Backward pass and optimization
optimizer.zero_grad()
loss.backward()
optimizer.step()
# Evaluate on validation set
with torch.no_grad():
= model(X_val)
val_outputs = torch.round(torch.sigmoid(val_outputs))
val_preds = accuracy_score(y_val.numpy(), val_preds.numpy())
accuracy
return accuracy
# Define a range of regularization rates to try
= [-1000, -6, -5, -4, -3, -2, -1.9, -1.8, -1, 0, 1]
log_reg_rates = [10**x for x in log_reg_rates]
reg_rates
= {}
accuracies
# Train and evaluate models for each regularization rate
for lam in reg_rates:
= train_and_evaluate_model(lam)
accuracy = accuracy
accuracies[lam] print(f'Regularization Rate: {lam}, Validation Accuracy: {accuracy}')
Regularization Rate: 0.0, Validation Accuracy: 0.872
Regularization Rate: 1e-06, Validation Accuracy: 0.8773333333333333
Regularization Rate: 1e-05, Validation Accuracy: 0.8773333333333333
Regularization Rate: 0.0001, Validation Accuracy: 0.8826666666666667
Regularization Rate: 0.001, Validation Accuracy: 0.8773333333333333
Regularization Rate: 0.01, Validation Accuracy: 0.8773333333333333
Regularization Rate: 0.012589254117941675, Validation Accuracy: 0.896
Regularization Rate: 0.015848931924611134, Validation Accuracy: 0.8933333333333333
Regularization Rate: 0.1, Validation Accuracy: 0.8693333333333333
Regularization Rate: 1, Validation Accuracy: 0.49066666666666664
Regularization Rate: 10, Validation Accuracy: 0.5093333333333333
= pd.Series(accuracies)
ser =True, style='o-') ser.plot(logx
<AxesSubplot:>