Logistic Regression Example

 

1. Import Packages

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!pip install seaborn livelossplot torchsummary torchmetrics

from tqdm import tqdm
from livelossplot import PlotLosses

import torch
from torch import nn
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader
from torchsummary import summary as summary_
import torchvision as tv
from torchvision import transforms
import torchmetrics as tm

def set_random_seed_torch(seed):
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = True

SEED = 42
set_random_seed_torch(SEED)

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
cuda   = lambda *xs: (x.to(device) for x in xs)

2. Load Dataset

1
2
3
4
5
6
7
8
train_ds = tv.datasets.MNIST(root='data', download=True, train=True, transform=transforms.ToTensor())
test_ds  = tv.datasets.MNIST(root='data', download=True, train=False, transform=transforms.ToTensor())
train_dl = DataLoader(train_data, batch_size=32, shuffle=True, drop_last=True, pin_memory=True)
test_dl  = DataLoader(test_data, batch_size=32, shuffle=False, pin_memory=True)

INPUT_SHAPE  = (1, 28, 28)
OUTPUT_SHAPE = 1
N_CLASSES    = 10

3. Import Packages

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
FILTERS     = 32
KERNEL_SIZE = 3
UNITS       = 128


class MyModel(nn.Module):
    def __init__(self, filters, kernel_size, units, n_classes, input_shape):
        super().__init__()
        self.input_shape = input_shape
        self.conv1       = nn.LazyConv2d(filters, kernel_size)
        self.d1          = nn.LazyLinear(units)
        self.output      = nn.LazyLinear(n_classes)
    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = x.flatten(start_dim=1)
        x = F.relu(self.d1(x))
        logits = self.output(x)
        return logits
    def summary(self):
        summary_(self, self.input_shape)


model     = cuda(MyModel(FILTERS, KERNEL_SIZE, UNITS, N_CLASSES, INPUT_SHAPE))
criterion = cuda(nn.CrossEntropyLoss())  # input: (logits, labels)
get_acc   = cuda(tm.Accuracy(task='multiclass', num_classes=N_CLASSES))
optimizer = torch.optim.Adam(model.parameters())  # to(device) 가 모두 완료된 이후에 정의
model.summary()
----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1           [-1, 32, 26, 26]             320
            Linear-2                  [-1, 128]       2,769,024
            Linear-3                   [-1, 10]           1,290
================================================================
Total params: 2,770,634
Trainable params: 2,770,634
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 0.17
Params size (MB): 10.57
Estimated Total Size (MB): 10.74
----------------------------------------------------------------

4. Training

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def train_step(images, labels):
    probs = model(images)
    loss  = criterion(probs, labels)
    acc   = get_acc(probs.argmax(1), labels)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    return loss, acc

def test_step(images, labels):
    probs = model(images)
    loss  = criterion(probs, labels)
    acc   = get_acc(probs.argmax(1), labels)
    return loss, acc

EPOCHS = 5
liveloss = PlotLosses()

rst = pd.DataFrame(columns=['loss', 'acc', 'val_loss', 'val_acc'], index=pd.Index([], name='Epoch'))
for epoch in tqdm(range(1, EPOCHS+1)):
    model.train()
    for images, labels in train_dl:
        images, labels = cuda(images, labels)
        loss, acc = train_step(images, labels)

    model.eval()
    with torch.no_grad():
        for test_images, test_labels in test_dl:
            test_images, test_labels = cuda(test_images, test_labels)
            val_loss, val_acc = test_step(test_images, test_labels)

    rst.loc[epoch] = [x.item() for x in (loss, acc, val_loss, val_acc)]
    liveloss.update(rst.loc[epoch])
    liveloss.send()
100%|██████████| 5/5 [00:31<00:00,  6.24s/it]
Accuracy
	training         	 (min:    1.000, max:    1.000, cur:    1.000)
	validation       	 (min:    1.000, max:    1.000, cur:    1.000)
Loss
	training         	 (min:    0.000, max:    0.004, cur:    0.000)
	validation       	 (min:    0.000, max:    0.000, cur:    0.000)