In [1]:
# restart your notebook if prompted on Colab
try:
import verta
except ImportError:
!pip install verta
This example features:
DataSet
utility for batching training data
In [2]:
HOST = "app.verta.ai"
PROJECT_NAME = "MNIST Multiclassification"
EXPERIMENT_NAME = "FC-NN"
In [3]:
# import os
# os.environ['VERTA_EMAIL'] =
# os.environ['VERTA_DEV_KEY'] =
In [4]:
from __future__ import print_function
import warnings
warnings.filterwarnings("ignore", category=FutureWarning)
import itertools
import time
import six
import numpy as np
import pandas as pd
from sklearn import datasets
import torch
import torch.nn as nn
import torch.nn.functional as func
import torch.optim as optim
import torch.utils.data as data_utils
In [5]:
data = datasets.load_digits()
X = data['data']
y = data['target']
In [6]:
df = pd.DataFrame(np.hstack((X, y.reshape(-1, 1))),
columns=["pixel_{}".format(i) for i in range(X.shape[-1])] + ['digit'])
df.head()
In [7]:
# gather indices to split training data into training and validation sets
shuffled_idxs = np.random.permutation(len(y))
idxs_train = shuffled_idxs[int(len(shuffled_idxs)/10):] # last 90%
idxs_val = shuffled_idxs[:int(len(shuffled_idxs)/10)] # first 10%
X_train, y_train = (torch.tensor(X[idxs_train], dtype=torch.float),
torch.tensor(y[idxs_train], dtype=torch.long))
X_val, y_val = (torch.tensor(X[idxs_val], dtype=torch.float),
torch.tensor(y[idxs_val], dtype=torch.long))
In [8]:
# create Dataset object to support batch training
class TrainingDataset(data_utils.Dataset):
def __init__(self, features, labels):
self.features = features
self.labels = labels
def __len__(self):
return len(self.labels)
def __getitem__(self, idx):
return (self.features[idx], self.labels[idx])
In [9]:
from verta import Client
from verta.utils import ModelAPI
client = Client(HOST)
proj = client.set_project(PROJECT_NAME)
expt = client.set_experiment(EXPERIMENT_NAME)
run = client.set_experiment_run()
In [10]:
hidden_size = 512
run.log_hyperparameter("hidden_size", hidden_size)
dropout = 0.2
run.log_hyperparameter("dropout", dropout)
class Net(nn.Module):
def __init__(self, num_features=X.shape[1],
hidden_size=hidden_size):
super(Net, self).__init__()
self.fc = nn.Linear(num_features, hidden_size)
self.dropout = nn.Dropout(dropout)
self.output = nn.Linear(hidden_size, 10)
def forward(self, x):
x = x.view(x.shape[0], -1) # flatten non-batch dimensions
x = func.relu(self.fc(x))
x = self.dropout(x)
x = func.softmax(self.output(x), dim=-1)
return x
In [11]:
# specify training procedure
model = Net()
criterion = torch.nn.CrossEntropyLoss()
run.log_hyperparameter("loss_fn", "cross entropy")
optimizer = torch.optim.Adam(model.parameters())
run.log_hyperparameter("optimizer", "adam")
num_epochs = 5
run.log_hyperparameter("num_epochs", num_epochs)
batch_size = 32
run.log_hyperparameter("batch_size", batch_size)
In [12]:
# enable batching of training data
dataset = TrainingDataset(X_train, y_train)
dataloader = data_utils.DataLoader(dataset,
batch_size=batch_size,
shuffle=True)
In [13]:
for i_epoch in range(num_epochs):
for i_batch, (X_batch, y_batch) in enumerate(dataloader):
model.zero_grad() # reset model gradients
output = model(X_batch) # conduct forward pass
loss = criterion(output, y_batch) # compare model output w/ ground truth
print("\repoch {}/{} | ".format(i_epoch+1, num_epochs), end='')
print("iteration {}/{} | ".format(i_batch+1, len(dataloader)), end='')
print("epoch loss avg: {}".format(loss.item()), end='')
loss.backward() # backpropogate loss to calculate gradients
optimizer.step() # update model weights
with torch.no_grad(): # no need to calculate gradients when assessing accuracy
print()
pred_train = model(X_train).numpy().argmax(axis=1)
train_acc = (pred_train == y_train.numpy()).mean()
print("Training accuracy: {}".format(train_acc))
run.log_observation("train_acc", train_acc)
pred_val = model(X_val).numpy().argmax(axis=1)
val_acc = (pred_val == y_val.numpy()).mean()
print("Validation accuracy: {}".format(val_acc))
run.log_observation("val_acc", val_acc)
In [14]:
run.log_code()
In [15]:
with torch.no_grad(): # no need to calculate gradients when assessing accuracy
pred_train = model(X_train).numpy().argmax(axis=1)
train_acc = (pred_train == y_train.numpy()).mean()
print("Training accuracy: {}".format(train_acc))
run.log_metric("train_acc", train_acc)
In [16]:
# create deployment artifacts
model_api = ModelAPI(X_train.tolist(), model(X_train).tolist())
requirements = ["torch"]
# save and log model
run.log_model(model, model_api=model_api)
run.log_requirements(requirements)
In [17]:
run
In [18]:
from verta._demo_utils import DeployedModel
deployed_model = DeployedModel(HOST, run.id)
In [19]:
for x in itertools.cycle(X.tolist()):
print(deployed_model.predict([x]))
time.sleep(.5)