Pytorch Basics

References

Building

[2]:
import numpy as np
import torch
from torch import nn
from torch.utils.data import DataLoader, Dataset, TensorDataset
[3]:
device = (
    "cuda"
    if torch.cuda.is_available()
    else "mps"
    if torch.backends.mps.is_available()
    else "cpu"
)
print(f"Available Device : {device}")
Available Device : cpu
[7]:
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

n_features = 10
n_samples = 50_000

temp_X, temp_y = make_classification(
    n_samples=n_samples,
    n_classes=2,
    n_features=n_features,
    class_sep=1,
    random_state=42,
)
X_train, X_test, y_train, y_test = train_test_split(
    temp_X.astype("float32"), temp_y.astype("float32"), stratify=temp_y, test_size=0.2
)

X_train.shape, y_train.shape, X_test.shape, y_test.shape
[7]:
((40000, 10), (40000,), (10000, 10), (10000,))
[8]:
batch_size = 64
train_dataloader = DataLoader(
    dataset=TensorDataset(
        torch.Tensor(X_train).to(device), torch.Tensor(y_train).to(device)
    ),
    batch_size=batch_size,
    shuffle=True,
)
test_dataloader = DataLoader(
    dataset=TensorDataset(
        torch.Tensor(X_train).to(device), torch.Tensor(y_train).to(device)
    ),
    batch_size=batch_size,
    shuffle=True,
)
[9]:
class NeuralNetwork(nn.Module):
    def __init__(self, n_inputs):
        super(NeuralNetwork, self).__init__()
        self.input_layer = nn.Linear(n_inputs, 32)
        self.relu = nn.ReLU()
        self.hidden_layer = nn.Linear(32, 32)
        self.output_layer = nn.Linear(32, 1)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x1 = self.relu(self.input_layer(x))
        x2 = self.relu(self.hidden_layer(x1))
        x3 = self.relu(self.hidden_layer(x2))
        output = self.sigmoid(self.output_layer(x3))
        return output


model = NeuralNetwork(n_features).to(device)
loss_fn = nn.BCELoss()
# optimizer = torch.optim.SGD(params=model.parameters(), lr=0.001)
optimizer = torch.optim.Adam(params=model.parameters())


def train(data_loader, model, loss_fn, optimizer):
    model.train()
    size = len(data_loader.dataset)
    for batch, (X, y) in enumerate(data_loader):
        # Compute prediction error
        pred = model(X)[:, 0]
        loss = loss_fn(pred, y)

        # Backpropagation
        optimizer.zero_grad()

        loss.backward()
        optimizer.step()

        if batch % 100 == 0:
            loss, current = loss.item(), (batch + 1) * len(X)
            print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")


def test(data_loader, model, loss_fn, thresh=0.5):
    size = len(data_loader.dataset)
    num_batches = len(data_loader)

    model.eval()
    test_loss, correct = 0, 0
    with torch.no_grad():
        for X, y in data_loader:
            pred = model(X)[:, 0]
            test_loss += loss_fn(pred, y).item()
            correct += (
                ((pred > thresh).type(torch.int) == y).type(torch.float).sum().item()
            )

    test_loss /= num_batches
    correct /= size
    print(
        f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n"
    )
[10]:
epochs = 5

for _ in range(epochs):
    train(train_dataloader, model, loss_fn, optimizer)
    test(test_dataloader, model, loss_fn)
loss: 0.684228  [   64/40000]
loss: 0.157080  [ 6464/40000]
loss: 0.116945  [12864/40000]
loss: 0.198458  [19264/40000]
loss: 0.043856  [25664/40000]
loss: 0.104556  [32064/40000]
loss: 0.164484  [38464/40000]
Test Error:
 Accuracy: 96.5%, Avg loss: 0.129747

loss: 0.091729  [   64/40000]
loss: 0.161205  [ 6464/40000]
loss: 0.035293  [12864/40000]
loss: 0.115426  [19264/40000]
loss: 0.121109  [25664/40000]
loss: 0.059457  [32064/40000]
loss: 0.176868  [38464/40000]
Test Error:
 Accuracy: 96.8%, Avg loss: 0.122206

loss: 0.079619  [   64/40000]
loss: 0.140084  [ 6464/40000]
loss: 0.070570  [12864/40000]
loss: 0.042990  [19264/40000]
loss: 0.120375  [25664/40000]
loss: 0.095633  [32064/40000]
loss: 0.040016  [38464/40000]
Test Error:
 Accuracy: 97.3%, Avg loss: 0.111193

loss: 0.037622  [   64/40000]
loss: 0.046972  [ 6464/40000]
loss: 0.093193  [12864/40000]
loss: 0.028648  [19264/40000]
loss: 0.027018  [25664/40000]
loss: 0.023192  [32064/40000]
loss: 0.073741  [38464/40000]
Test Error:
 Accuracy: 97.4%, Avg loss: 0.107557

loss: 0.154942  [   64/40000]
loss: 0.096006  [ 6464/40000]
loss: 0.030325  [12864/40000]
loss: 0.105037  [19264/40000]
loss: 0.141436  [25664/40000]
loss: 0.060033  [32064/40000]
loss: 0.093308  [38464/40000]
Test Error:
 Accuracy: 97.2%, Avg loss: 0.106574