ํด๋น ๊ธ์ FastCampus - '๋ชจ๋๋ฅผ ์ํ 2025 AI ๋ฐ์ด๋ธ : AI Signature' ๊ฐ์๋ฅผ ๋ฃ๊ณ ,
์ถ๊ฐ ํ์ตํ ๋ด์ฉ์ ๋ง๋ถ์ฌ ์์ฑํ์์ต๋๋ค.
!git clone https://github.com/ndb796/weather_dataset
%cd weather_dataset # ํ์ฌ ์์
๋๋ ํ ๋ฆฌ๋ฅผ weather_dataset ํด๋๋ก ๋ณ๊ฒฝ
import torch
import torchvision
import torchvision.transforms as transforms
import torchvision.models as models
import torchvision.datasets as datasets
import torch.optim as optim
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import random_split
import matplotlib.pyplot as plt
import matplotlib.image as image
import numpy as np
Data Augmentation
ํ์ต ๋ฐ์ดํฐ๋ฅผ ๋๋ฆฌ๊ฑฐ๋ ๋ค์ํ๊ฒ ๋ง๋๋ ๊ธฐ๋ฒ
์: ์ด๋ฏธ์ง๋ฅผ ํ์ , ๋ค์ง๊ธฐ, ๋ฐ๊ธฐ ์กฐ์ ๋ฑ์ผ๋ก ๋ค์ํ๊ฒ ๋ณํ
# ์ด๋ฏธ์ง ์ ์ฒ๋ฆฌ: ํ์ต์ฉ ๋ฐ์ดํฐ์ ์ ์ฉํ torchvision์ transforms๋ก ์์ฐจ์ ์ ์ฒ๋ฆฌ ์ ์
transform_train = transforms.Compose([
transforms.Resize((256, 256)), # ๋ชจ๋ ์ด๋ฏธ์ง๋ฅผ 256x256 ํฌ๊ธฐ๋ก resize by Bilinear interpolation (2D)
# ์ ํฝ์
๊ฐ์ ๊ณ์ฐํ ๋, ์ฃผ๋ณ ๊ฐ์ฅ ๊ฐ๊น์ด 2ร2 ํฝ์
(์ด 4๊ฐ)์ ์ฐธ๊ณ ํด์ ๋ณด๊ฐ
transforms.RandomHorizontalFlip(), # ์ข์ฐ๋ก ์ด๋ฏธ์ง ๋ค์ง๊ธฐ (๋ฐ์ดํฐ ์ฆ๊ฐ)
transforms.ToTensor(), # PIL ์ด๋ฏธ์ง โ Tensor๋ก ๋ณํ, [0, 1] ์ค์ผ์ผ๋ง
transforms.Normalize( # ์ด๋ฏธ์ง ์ ๊ทํ (0~1 โ -1~1)
mean=[0.5, 0.5, 0.5], # RGB ํ๊ท
std=[0.5, 0.5, 0.5] # RGB ํ์คํธ์ฐจ
)
])
# ๊ฒ์ฆ(validation)์ฉ ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ: ํ์ต๊ณผ๋ ๋ค๋ฅด๊ฒ ๋ฐ์ดํฐ ์ฆ๊ฐ ์์
transform_val = transforms.Compose([
transforms.Resize((256, 256)), # ํฌ๊ธฐ๋ง ์กฐ์
transforms.ToTensor(),
transforms.Normalize(
mean=[0.5, 0.5, 0.5],
std=[0.5, 0.5, 0.5]
)
])
# ํ
์คํธ ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ๋ ๊ฒ์ฆ๊ณผ ๋์ผ (์ผ๊ด์ฑ ์๊ฒ ์ฆ๊ฐ ์์ด)
transform_test = transforms.Compose([
transforms.Resize((256, 256)),
transforms.ToTensor(),
transforms.Normalize(
mean=[0.5, 0.5, 0.5],
std=[0.5, 0.5, 0.5]
)
])
# ํ์ต์ฉ ๋ฐ์ดํฐ์
๋ก๋ฉ (ImageFolder: ํด๋๋ช
์ ๋ผ๋ฒจ๋ก ์๋ ๋งคํํด์ค)
train_dataset = datasets.ImageFolder(
root='train/', # ํ์ต ์ด๋ฏธ์ง๊ฐ ๋ค์ด ์๋ ํด๋
transform=transform_train # ์์์ ์ ์ํ transform ์ ์ฉ
)
# ์ ์ฒด ํ์ต ๋ฐ์ดํฐ ์ค ์ผ๋ถ๋ฅผ ๊ฒ์ฆ์ฉ์ผ๋ก ๋ถํ
dataset_size = len(train_dataset) # ์ ์ฒด ๋ฐ์ดํฐ ๊ฐ์
train_size = int(dataset_size * 0.8) # 80% ํ์ต์ฉ
val_size = dataset_size - train_size # 20% ๊ฒ์ฆ์ฉ
# ํ์ต / ๊ฒ์ฆ ๋ฐ์ดํฐ์
์ผ๋ก ๋ถ๋ฆฌ
train_dataset, val_dataset = random_split(train_dataset, [train_size, val_size])
val_dataset.dataset.transform = transform_val
# ํ
์คํธ ๋ฐ์ดํฐ์
๋ก๋ฉ (๋ผ๋ฒจ๋ ์๋ ๋งคํ๋จ)
test_dataset = datasets.ImageFolder(
root='test/',
transform=transform_test
)
# ๋ฐ์ดํฐ๋ก๋(DataLoader) ์ค์ : ๋ฐฐ์น ๋จ์๋ก ๋ฐ์ดํฐ๋ฅผ ๋ก๋ฉ
train_dataloader = torch.utils.data.DataLoader(
train_dataset, batch_size=64, shuffle=True # ํ์ต์ฉ: ๋งค epoch๋ง๋ค ์๊ธฐ
)
val_dataloader = torch.utils.data.DataLoader(
val_dataset, batch_size=64, shuffle=False # ๊ฒ์ฆ์ฉ: ์์ ๊ณ ์
)
test_dataloader = torch.utils.data.DataLoader(
test_dataset, batch_size=64, shuffle=False # ํ
์คํธ์ฉ: ์์ ๊ณ ์
)
# ์๊ฐํ ์ค์
plt.rcParams['figure.figsize'] = [12, 8] # ๊ทธ๋ํ ํฌ๊ธฐ ์ค์
plt.rcParams['figure.dpi'] = 60 # ํด์๋ ์ค์
plt.rcParams.update({'font.size': 20}) # ๊ธ๊ผด ํฌ๊ธฐ ์ค์
# ์ด๋ฏธ์ง ์ถ๋ ฅ ํจ์ ์ ์
def imshow(input):
# ํ
์ โ ๋ํ์ด๋ก ๋ณํ, ์ฑ๋ ์์๋ (C, H, W) โ (H, W, C)๋ก ๋ณ๊ฒฝ
input = input.numpy().transpose((1, 2, 0))
# ์ ๊ทํ ํด์ (์๋ ์ด๋ฏธ์ง ๊ฐ์ผ๋ก ๋ณต์)
mean = np.array([0.5, 0.5, 0.5])
std = np.array([0.5, 0.5, 0.5])
input = std * input + mean
input = np.clip(input, 0, 1) # ๊ฐ ๋ฒ์ 0~1๋ก ์ ํ
# ์ด๋ฏธ์ง ์ถ๋ ฅ
plt.imshow(input)
plt.show()
# ํด๋์ค ๋ผ๋ฒจ ์ด๋ฆ ์ ์
class_names = {
0: "Cloudy",
1: "Rain",
2: "Shine",
3: "Sunrise"
}
# ํ์ต ์ด๋ฏธ์ง ๋ฐฐ์น ํ๋ ๋ก๋
iterator = iter(train_dataloader) # DataLoader๋ฅผ ์ดํฐ๋ ์ดํฐ๋ก ๋ณํ
imgs, labels = next(iterator) # ์ฒซ ๋ฐฐ์น ๋ก๋
# ์ด๋ฏธ์ง ๊ทธ๋ฆฌ๋๋ก ๋ฌถ๊ธฐ (์์์ 4์ฅ๋ง ๋ณด๊ธฐ)
out = torchvision.utils.make_grid(imgs[:4])
# ์ด๋ฏธ์ง ์ถ๋ ฅ
imshow(out)
# ํด๋น ์ด๋ฏธ์ง๋ค์ ํด๋์ค ์ด๋ฆ ์ถ๋ ฅ
print([class_names[labels[i].item()] for i in range(4)])
Output

['Rain', 'Sunrise', 'Sunrise', 'Shine']
๋ชจ๋ธ ์ ์
import torch.nn as nn
import torch.nn.functional as F
# ๋จ์ผ ์ ํ์ธต๋ง ์๋ ์์ฃผ ๋จ์ํ ๋ชจ๋ธ
class Model1(nn.Module):
def __init__(self):
super(Model1, self).__init__() # forward, parameters(), .to(device) ๊ฐ์ ๋ถ๋ชจ ํด๋์ค ๊ธฐ๋ฅ ์ฌ์ฉํ๊ธฐ ์ํด ๋ถ๋ชจ ํด๋์ค ์ด๊ธฐํ
self.flatten = nn.Flatten()
self.linear1 = nn.Linear(256 * 256 * 3, 4) # ์
๋ ฅ์ flatten ํ ๋ฐ๋ก ํด๋์ค 4๊ฐ๋ก ๋งคํ
def forward(self, x):
x = self.flatten(x) # ์ด๋ฏธ์ง(3x256x256) โ 1D ๋ฒกํฐ
x = self.linear1(x) # ์ ํ ๋ณํ
return x
# ์๋์ธต(hidden layer) 1๊ฐ ์ถ๊ฐ๋ ๋ชจ๋ธ
class Model2(nn.Module):
def __init__(self):
super(Model2, self).__init__()
self.flatten = nn.Flatten()
self.linear1 = nn.Linear(256 * 256 * 3, 64) # ์ฒซ ๋ฒ์งธ ์๋์ธต
self.linear2 = nn.Linear(64, 4) # ์ถ๋ ฅ์ธต
def forward(self, x):
x = self.flatten(x)
x = self.linear1(x) # ์๋์ธต (ํ์ฑํ ํจ์ ์์)
x = self.linear2(x)
return x
# ์๋์ธต + ๋๋กญ์์์ด ํฌํจ๋ ์ฌ์ธต ๋ชจ๋ธ
class Model3(nn.Module):
def __init__(self):
super(Model3, self).__init__()
self.flatten = nn.Flatten()
self.linear1 = nn.Linear(256 * 256 * 3, 128)
self.dropout1 = nn.Dropout(0.5)
self.linear2 = nn.Linear(128, 64)
self.dropout2 = nn.Dropout(0.5)
self.linear3 = nn.Linear(64, 32)
self.dropout3 = nn.Dropout(0.5)
self.linear4 = nn.Linear(32, 4) # ์ต์ข
ํด๋์ค 4๊ฐ ์ถ๋ ฅ
def forward(self, x):
x = self.flatten(x)
x = F.relu(self.linear1(x)) # ReLU + Dropout ๋ฐ๋ณต
x = self.dropout1(x)
x = F.relu(self.linear2(x))
x = self.dropout2(x)
x = F.relu(self.linear3(x))
x = self.dropout3(x)
x = self.linear4(x)
return x
# resnet50(ImageNet==๋๊ท๋ชจ ์ด๋ฏธ์ง ๋ฐ์ดํฐ์
์ ์ด๋ฏธ ํ๋ จ์ํจ ๋ชจ๋ธ)์ transfer learning(์ด๋ฏธ ํ๋ จ๋ ๋ชจ๋ธ์ ๊ฐ์ ธ์์ ๋ชฉ์ ์ ๋ง๊ฒ ์ฌ์ฌ์ฉ)
class ModelTransfer(nn.Module):
def __init__(self):
super(ModelTransfer, self).__init__()
# ResNet50 ๋ชจ๋ธ ๋ถ๋ฌ์ค๊ธฐ
model = models.resnet50(pretrained=True)
num_features = model.fc.in_features # ๋ง์ง๋ง FC ๋ ์ด์ด์ ๋ค์ด์ค๋ ์
๋ ฅ ํฌ๊ธฐ (2048)
# model.fc.in_features โ 2048 (์
๋ ฅ ํฌ๊ธฐ)
# model.fc.out_features โ 1000 (์ถ๋ ฅ ํฌ๊ธฐ)
model.fc = nn.Linear(num_features, 4) # fc(fully connected layer, ๋ง์ง๋ง Layer)์์ output ์ฐจ์์ 1000๊ฐ ํด๋์ค ๋์ ๋ด๊ฐ ์ํ๋ 4๊ฐ ํด๋์ค ๋ถ๋ฅ๊ธฐ๋ก ๊ต์ฒด
self.model = model # self.model๋ก ์ ์ฅ
def forward(self, x): # ๋ฉ์๋ ์ค๋ฒ๋ผ์ด๋ฉ
return self.model(x) # forward ๋ฉ์๋์์ ๋ชจ๋ธ ์คํ
๋ชจ๋ธ ํ์ต, ๊ฒ์ฆ, ํ
์คํธ ํจ์ ์ ์
import time
# ํ์ต ํจ์
def train():
start_time = time.time()
print(f'[Epoch: {epoch + 1} - Training]')
model.train() # ๋ชจ๋ธ์ ํ์ต ๋ชจ๋๋ก ์ค์
total = 0
running_loss = 0.0
running_corrects = 0
for i, batch in enumerate(train_dataloader):
imgs, labels = batch
imgs, labels = imgs.cuda(), labels.cuda() # GPU๋ก ์ด๋
outputs = model(imgs) # ์์ ํ
optimizer.zero_grad() # ์ด์ ๊ธฐ์ธ๊ธฐ ์ด๊ธฐํ
_, preds = torch.max(outputs, 1) # ํด๋์ค ์ฐจ์(1๋ฒ ์ถ)์์ ๊ฐ์ฅ ํฐ ๊ฐ์ index๋ฅผ ๋ฐํ
loss = criterion(outputs, labels) # ์์ค ๊ณ์ฐ
loss.backward() # ์ญ์ ํ โ ๊ธฐ์ธ๊ธฐ ๊ณ์ฐ
optimizer.step() # ํ๋ผ๋ฏธํฐ ์
๋ฐ์ดํธ
total += labels.shape[0]
running_loss += loss.item() # ์ฐ์ฐ ๊ทธ๋ํ์ loss ๊ฐ์ ๋ด๊ณ ์๋ tensor์์ loss ์ซ์(float)๋ฅผ ๊บผ๋ด๋ ํจ์
running_corrects += torch.sum(preds == labels.data)
# ์ผ์ step๋ง๋ค ๋ก๊ทธ ์ถ๋ ฅ
if i % log_step == log_step - 1:
print(f'[Batch: {i + 1}] running train loss: {running_loss / total}, running train accuracy: {running_corrects / total}')
print(f'train loss: {running_loss / total}, accuracy: {running_corrects / total}')
print("elapsed time:", time.time() - start_time)
return running_loss / total, (running_corrects / total).item()
# ๊ฒ์ฆ ํจ์
def validate():
start_time = time.time()
print(f'[Epoch: {epoch + 1} - Validation]')
model.eval() # ๋ชจ๋ธ์ ํ๊ฐ ๋ชจ๋๋ก ์ค์
total = 0
running_loss = 0.0
running_corrects = 0
for i, batch in enumerate(val_dataloader):
imgs, labels = batch
imgs, labels = imgs.cuda(), labels.cuda()
with torch.no_grad(): # ๊ธฐ์ธ๊ธฐ ์ถ์ ๋นํ์ฑํ โ ๋ ๋น ๋ฅด๊ณ ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ
outputs = model(imgs)
max_values, preds = torch.max(outputs, 1)
loss = criterion(outputs, labels)
total += labels.shape[0]
running_loss += loss.item()
running_corrects += torch.sum(preds == labels.data)
if (i == 0) or (i % log_step == log_step - 1):
print(f'[Batch: {i + 1}] running val loss: {running_loss / total}, running val accuracy: {running_corrects / total}')
print(f'val loss: {running_loss / total}, accuracy: {running_corrects / total}')
print("elapsed time:", time.time() - start_time)
return running_loss / total, (running_corrects / total).item()
# ํ
์คํธ ํจ์ (๊ฒ์ฆ๊ณผ ๊ฑฐ์ ๋์ผ)
def test():
start_time = time.time()
print(f'[Test]')
model.eval()
total = 0
running_loss = 0.0
running_corrects = 0
for i, batch in enumerate(test_dataloader):
imgs, labels = batch
imgs, labels = imgs.cuda(), labels.cuda()
with torch.no_grad():
outputs = model(imgs)
_, preds = torch.max(outputs, 1)
loss = criterion(outputs, labels)
total += labels.shape[0]
running_loss += loss.item()
running_corrects += torch.sum(preds == labels.data)
if (i == 0) or (i % log_step == log_step - 1):
print(f'[Batch: {i + 1}] running test loss: {running_loss / total}, running test accuracy: {running_corrects / total}')
print(f'test loss: {running_loss / total}, accuracy: {running_corrects / total}')
print("elapsed time:", time.time() - start_time)
return running_loss / total, (running_corrects / total).item()
ํ์ต๋ฅ (learning rate)์ epoch ์์ ๋ฐ๋ผ ์กฐ์ ํ๋ ํจ์
์ด๋ฐ์๋ ํฐ ํ์ต๋ฅ ๋ก ๋น ๋ฅด๊ฒ ํ์ต
โ ๋น ๋ฅด๊ฒ ์ต์ ์ ๊ทผ์ฒ๋ก ์ด๋
ํ๋ฐ์๋ ์์ ํ์ต๋ฅ ๋ก ๋ฏธ์ธํ๊ฒ ํ๋
โ ์ด๋ฏธ ์ด๋ ์ ๋ ์ข์ ์ง์ ์ ๋๋ฌ, ๋๋ฌด ํฌ๊ฒ ์์ง์ด๋ฉด ์คํ๋ ค ์ต์ ์ ์ ์ง๋์ณ ๋ฒ๋ฆด ์ ์์
์ค๋ฒ ํผํ ์ ์ค์ด๊ณ ์ผ๋ฐํ ์ฑ๋ฅ์ ์ค์ฌ ๋ ์ข์ ์ฑ๋ฅ๊ณผ ์์ ์ ์ธ ์๋ ด์ ์ป์ ์ ์์
import time
def adjust_learning_rate(optimizer, epoch):
lr = learning_rate # ์ด๊ธฐ ํ์ต๋ฅ ์ ๊ฐ์ ธ์ด
# epoch >= 3์ผ ๋ ํ์ต๋ฅ ์ 1/10๋ก ๊ฐ์
if epoch >= 3:
lr /= 10
# epoch >= 7์ผ ๋ ๋ค์ ํ ๋ฒ 1/10๋ก ๊ฐ์ (์ฆ, ์๋์ 1/100)
if epoch >= 7:
lr /= 10
# optimizer์ ์๋ ๋ชจ๋ ํ๋ผ๋ฏธํฐ ๊ทธ๋ฃน์ ํ์ต๋ฅ ์ ๋ณ๊ฒฝ
for param_group in optimizer.param_groups:
param_group['lr'] = lr
learning_rate = 0.01
log_step = 20
model = Model1()
model = model.cuda()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=learning_rate, momentum=0.9)
num_epochs = 20
best_val_acc = 0
best_epoch = 0
history = []
accuracy = []
for epoch in range(num_epochs):
adjust_learning_rate(optimizer, epoch)
train_loss, train_acc = train()
val_loss, val_acc = validate()
history.append((train_loss, val_loss))
accuracy.append((train_acc, val_acc))
if val_acc > best_val_acc:
print("[Info] best validation accuracy!")
best_val_acc = val_acc
best_epoch = epoch
torch.save(model.state_dict(), f"best_checkpoint_epoch_{epoch + 1}.pth")
torch.save(model.state_dict(), f"last_checkpoint_epoch_{num_epochs}.pth")
plt.plot([x[0] for x in accuracy], 'b', label='train')
plt.plot([x[1] for x in accuracy], 'r--',label='validation')
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.legend()
test_loss, test_accuracy = test()
print(f"Test loss: {test_loss:.8f}")
print(f"Test accuracy: {test_accuracy * 100.:.2f}%")
Output
[Epoch: 1 - Training]
train loss: 0.2685530501824838, accuracy: 0.6029629707336426
elapsed time: 6.362705230712891
[Epoch: 1 - Validation]
[Batch: 1] running val loss: 0.25105223059654236, running val accuracy: 0.65625
val loss: 0.36737381071734004, accuracy: 0.692307710647583
elapsed time: 1.214353322982788
[Info] best validation accuracy!
...
[Epoch: 20 - Training]
train loss: 0.05483319741708261, accuracy: 0.8414815068244934
elapsed time: 5.412205696105957
[Epoch: 20 - Validation]
[Batch: 1] running val loss: 0.1295606642961502, running val accuracy: 0.734375
val loss: 0.1441787206209623, accuracy: 0.7337278127670288
elapsed time: 1.2089176177978516
[Test]
[Batch: 1] running test loss: 0.2731671631336212, running test accuracy: 0.625
test loss: 0.17309151234575862, accuracy: 0.7295373678207397
elapsed time: 0.9299411773681641
Test loss: 0.17309151
Test accuracy: 72.95%

learning_rate = 0.01
log_step = 20
model = Model2()
model = model.cuda()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=learning_rate, momentum=0.9)
num_epochs = 20
best_val_acc = 0
best_epoch = 0
history = []
accuracy = []
for epoch in range(num_epochs):
adjust_learning_rate(optimizer, epoch)
train_loss, train_acc = train()
val_loss, val_acc = validate()
history.append((train_loss, val_loss))
accuracy.append((train_acc, val_acc))
if val_acc > best_val_acc:
print("[Info] best validation accuracy!")
best_val_acc = val_acc
best_epoch = epoch
torch.save(model.state_dict(), f"best_checkpoint_epoch_{epoch + 1}.pth")
torch.save(model.state_dict(), f"last_checkpoint_epoch_{num_epochs}.pth")
plt.plot([x[0] for x in accuracy], 'b', label='train')
plt.plot([x[1] for x in accuracy], 'r--',label='validation')
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.legend()
test_loss, test_accuracy = test()
print(f"Test loss: {test_loss:.8f}")
print(f"Test accuracy: {test_accuracy * 100.:.2f}%")
Output
[Epoch: 1 - Training]
train loss: 0.062059673556575067, accuracy: 0.5688889026641846
elapsed time: 7.238025426864624
[Epoch: 1 - Validation]
[Batch: 1] running val loss: 0.10530433803796768, running val accuracy: 0.359375
val loss: 0.10420821263239934, accuracy: 0.4201183617115021
elapsed time: 1.2768044471740723
[Info] best validation accuracy!
...
[Epoch: 20 - Training]
train loss: 0.04108952063101309, accuracy: 0.7881481647491455
elapsed time: 7.323403835296631
[Epoch: 20 - Validation]
[Batch: 1] running val loss: 0.06464774161577225, running val accuracy: 0.609375
val loss: 0.0676442956077982, accuracy: 0.6568047404289246
elapsed time: 1.3936107158660889
[Test]
[Batch: 1] running test loss: 0.10629818588495255, running test accuracy: 0.484375
test loss: 0.07723092860492523, accuracy: 0.6832740306854248
elapsed time: 1.1223466396331787
Test loss: 0.07723093
Test accuracy: 68.33%

learning_rate = 0.01
log_step = 20
model = Model3()
model = model.cuda()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=learning_rate, momentum=0.9)
num_epochs = 20
best_val_acc = 0
best_epoch = 0
history = []
accuracy = []
for epoch in range(num_epochs):
adjust_learning_rate(optimizer, epoch)
train_loss, train_acc = train()
val_loss, val_acc = validate()
history.append((train_loss, val_loss))
accuracy.append((train_acc, val_acc))
if val_acc > best_val_acc:
print("[Info] best validation accuracy!")
best_val_acc = val_acc
best_epoch = epoch
torch.save(model.state_dict(), f"best_checkpoint_epoch_{epoch + 1}.pth")
torch.save(model.state_dict(), f"last_checkpoint_epoch_{num_epochs}.pth")
plt.plot([x[0] for x in accuracy], 'b', label='train')
plt.plot([x[1] for x in accuracy], 'r--',label='validation')
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.legend()
test_loss, test_accuracy = test()
print(f"Test loss: {test_loss:.8f}")
print(f"Test accuracy: {test_accuracy * 100.:.2f}%")
Output
[Epoch: 1 - Training]
train loss: 0.021055312863102665, accuracy: 0.3733333349227905
elapsed time: 7.819769620895386
[Epoch: 1 - Validation]
[Batch: 1] running val loss: 0.014086698181927204, running val accuracy: 0.671875
val loss: 0.014450000588005111, accuracy: 0.6449704170227051
elapsed time: 1.6248998641967773
[Info] best validation accuracy!
...
[Epoch: 20 - Training]
train loss: 0.013426496452755399, accuracy: 0.6651852130889893
elapsed time: 7.245265483856201
[Epoch: 20 - Validation]
[Batch: 1] running val loss: 0.010319100692868233, running val accuracy: 0.8125
val loss: 0.011233355166644034, accuracy: 0.7869822382926941
elapsed time: 1.279524326324463
[Test]
[Batch: 1] running test loss: 0.016797732561826706, running test accuracy: 0.78125
test loss: 0.011137271594932283, accuracy: 0.836298942565918
elapsed time: 1.0040242671966553
Test loss: 0.01113727
Test accuracy: 83.63%

learning_rate = 0.01
log_step = 20
model = ModelTransfer()
model = model.cuda()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=learning_rate, momentum=0.9)
num_epochs = 20
best_val_acc = 0
best_epoch = 0
history = []
accuracy = []
for epoch in range(num_epochs):
adjust_learning_rate(optimizer, epoch)
train_loss, train_acc = train()
val_loss, val_acc = validate()
history.append((train_loss, val_loss))
accuracy.append((train_acc, val_acc))
if val_acc > best_val_acc:
print("[Info] best validation accuracy!")
best_val_acc = val_acc
best_epoch = epoch
torch.save(model.state_dict(), f"best_checkpoint_epoch_{epoch + 1}.pth")
torch.save(model.state_dict(), f"last_checkpoint_epoch_{num_epochs}.pth")
plt.plot([x[0] for x in accuracy], 'b', label='train')
plt.plot([x[1] for x in accuracy], 'r--',label='validation')
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.legend()
test_loss, test_accuracy = test()
print(f"Test loss: {test_loss:.8f}")
print(f"Test accuracy: {test_accuracy * 100.:.2f}%")
Output
[Epoch: 1 - Training]
train loss: 0.011269845013265256, accuracy: 0.742222249507904
elapsed time: 13.960606813430786
[Epoch: 1 - Validation]
[Batch: 1] running val loss: 0.0027156963478773832, running val accuracy: 0.921875
val loss: 0.004075330301854738, accuracy: 0.9349112510681152
elapsed time: 1.6107542514801025
[Info] best validation accuracy!
...
[Epoch: 20 - Training]
train loss: 9.46323561516625e-05, accuracy: 1.0
elapsed time: 13.069997072219849
[Epoch: 20 - Validation]
[Batch: 1] running val loss: 0.00017253367695957422, running val accuracy: 1.0
val loss: 0.001278820651522755, accuracy: 0.9704142212867737
elapsed time: 1.609588861465454
[Test]
[Batch: 1] running test loss: 0.0005804044776596129, running test accuracy: 0.984375
test loss: 0.0012308261295104418, accuracy: 0.982206404209137
elapsed time: 1.8220326900482178
Test loss: 0.00123083
Test accuracy: 98.22%
