10.1 Hluboké učení - Konvoluční neuronové sítě - klasifikace¶
Úkol: Tento notebook představuje klasifikaci objektů pomocí CNN modelu naprogramovaného pomocí knihovny PyTorch. Příklad zahrnuje klasifikaci simulovaných objektů (trojuhelník, čtverec, kruh) v náhodné poloze.
Architektura: Plně propojená síť (po vzoru FCN) pro klasifikaci
Úkoly:¶
- Vypracujte celý pracovní postup s CNN architekturou pro klasifikaci tvaru objektu, včetně implementace modelu a nastavení parametrů modelování.
- Změňte úroveň šumu z 0,1 na 0,5 a 0,9 a vyhodnoťte přesnost učení.
Příklad CNN architektury¶
Hlavní kroky pracovního postupu modelování¶
- Načtení datové sady
- Vytvoření iterovatelné datové sady
- Vytvoření třídy modelu
- Instance třídy modelu
- Instance třídy ztráty
- Instance třídy optimalizátoru
- Trénování modelu
In [ ]:
Copied!
import numpy as np
np.random.seed(42)
import matplotlib.pyplot as plt
import time
# PyTorch imports
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
from torch.autograd import Variable
import numpy as np
np.random.seed(42)
import matplotlib.pyplot as plt
import time
# PyTorch imports
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
from torch.autograd import Variable
Simulated data¶
In [ ]:
Copied!
# Skript pro simulaci dat
from simulate_images import generate_image_shapes
# Skript pro simulaci dat
from simulate_images import generate_image_shapes
In [ ]:
Copied!
# Generování dat
height, width, count = 28, 28, 9
noise = 0.2
X, Y, y_label = generate_image_shapes(height, width, count, noise)
# Generování dat
height, width, count = 28, 28, 9
noise = 0.2
X, Y, y_label = generate_image_shapes(height, width, count, noise)
In [ ]:
Copied!
X.shape
X.shape
In [ ]:
Copied!
Y.shape
Y.shape
In [ ]:
Copied!
y_label
y_label
In [ ]:
Copied!
np.unique(y_label)
np.unique(y_label)
In [ ]:
Copied!
image_no=7
print(f'Label: {y_label[image_no]}')
plt.imshow(X[image_no][0,:,:])
image_no=7
print(f'Label: {y_label[image_no]}')
plt.imshow(X[image_no][0,:,:])
In [ ]:
Copied!
plt.figure(figsize=(10,10))
for i in range(count):
plt.subplot(3, 3, i+1)
plt.imshow(X[i, 0, :, :])
plt.figure(figsize=(10,10))
for i in range(count):
plt.subplot(3, 3, i+1)
plt.imshow(X[i, 0, :, :])
1. Třída Dataset pro načtení datové sady¶
In [ ]:
Copied!
class SimDataset(Dataset):
def __init__(self, height, width, count, noise, transform=None):
self.input_images, self.target_masks, self.target_labels = generate_image_shapes(
height, width, count, noise
)
self.transform = transform
def __len__(self):
return len(self.input_images)
def __getitem__(self, idx):
image = self.input_images[idx]
mask = self.target_masks[idx]
label = self.target_labels[idx]
if self.transform:
image = self.transform(image)
return (image, mask, label)
class SimDataset(Dataset):
def __init__(self, height, width, count, noise, transform=None):
self.input_images, self.target_masks, self.target_labels = generate_image_shapes(
height, width, count, noise
)
self.transform = transform
def __len__(self):
return len(self.input_images)
def __getitem__(self, idx):
image = self.input_images[idx]
mask = self.target_masks[idx]
label = self.target_labels[idx]
if self.transform:
image = self.transform(image)
return (image, mask, label)
In [ ]:
Copied!
# test
height, width, count = 28, 28, 9
noise = 0.1
train_size = 1
sd = SimDataset(height, width, train_size, noise)
# test
height, width, count = 28, 28, 9
noise = 0.1
train_size = 1
sd = SimDataset(height, width, train_size, noise)
In [ ]:
Copied!
dl = DataLoader(sd, batch_size=1, shuffle=True, num_workers=0)
sample = next(iter(dl))
sample[0].shape
dl = DataLoader(sd, batch_size=1, shuffle=True, num_workers=0)
sample = next(iter(dl))
sample[0].shape
2. Vytvoření iterovatelného datasetu¶
In [ ]:
Copied!
# Vytvořte instance simulovaných dat pro trénovaní a testování pomocí třídy SimDataset
# train_set: height, width = 28, 28, size = 500, noise = 0.1
# test_set: height, width = 28, 28, size = 500, noise = 0.1
pass
# Vytvořte instance simulovaných dat pro trénovaní a testování pomocí třídy SimDataset
# train_set: height, width = 28, 28, size = 500, noise = 0.1
# test_set: height, width = 28, 28, size = 500, noise = 0.1
pass
In [ ]:
Copied!
# Vytvořte instance iterátoru DataLoader z připravených train_set a test set.
# train_dataloader: train_set, batch_size = 9, shuffle=True, num_workers=0
# test_dataloader: test_set, batch_size = 9, shuffle=False, num_workers=0
pass
# Vytvořte instance iterátoru DataLoader z připravených train_set a test set.
# train_dataloader: train_set, batch_size = 9, shuffle=True, num_workers=0
# test_dataloader: test_set, batch_size = 9, shuffle=False, num_workers=0
pass
In [ ]:
Copied!
# otestujte dataloder
pass
# otestujte dataloder
pass
In [ ]:
Copied!
pass
pass
3: Definice Modelu¶
In [ ]:
Copied!
# CNN Model
# ---
# Konvoluce 2D 1: in = 1, channels = 16, kernel = 5 , stride=1, padding=2
# Aktivace ReLU
# Max Pool" nn.MaxPool(kernel_size=2)
# Konvoluce 2D 2: in = 16, channels = 16, kernel = 5, stride=1, padding=2
# Aktivace ReLU
# Max Pool" nn.MaxPool(kernel_size=2)
# Plně propojený lineární výstup 1: 16 * 7 * 7, výstup = 3
class CNNModel(nn.Module):
def __init__(self):
super(CNNModel, self).__init__()
# Konvoluce 1 nn.Conv2d()
self.cnn1 = pass
# Aktivace nn.ReLU()
self.relu1 = pass
# Max pool 1
self.maxpool1 = nn.MaxPool2d(kernel_size=2)
# Konvoluce 2 nn.Conv2d
self.cnn2 = pass
self.relu2 = pass
# Max pool 2 nn.MaxPool2d()
self.maxpool2 = pass
# Plně propojený lineární výstup nn.Linear(), vstup 16 * 7 * 7, výstup 3 třídy
self.fc1 = pass
def forward(self, x):
# Konvoluce 1
out = pass
# Relu
out = pass
# Max pool 1
out = pass
# Konvoluce 2
out = pass
# Relu
out = pass
# Max pool 2
out = pass
# Změna velikosti - zploštění dat
out = out.view(out.size(0), -1)
# Plně propojený lineární výstup
out = pass
return out
# CNN Model
# ---
# Konvoluce 2D 1: in = 1, channels = 16, kernel = 5 , stride=1, padding=2
# Aktivace ReLU
# Max Pool" nn.MaxPool(kernel_size=2)
# Konvoluce 2D 2: in = 16, channels = 16, kernel = 5, stride=1, padding=2
# Aktivace ReLU
# Max Pool" nn.MaxPool(kernel_size=2)
# Plně propojený lineární výstup 1: 16 * 7 * 7, výstup = 3
class CNNModel(nn.Module):
def __init__(self):
super(CNNModel, self).__init__()
# Konvoluce 1 nn.Conv2d()
self.cnn1 = pass
# Aktivace nn.ReLU()
self.relu1 = pass
# Max pool 1
self.maxpool1 = nn.MaxPool2d(kernel_size=2)
# Konvoluce 2 nn.Conv2d
self.cnn2 = pass
self.relu2 = pass
# Max pool 2 nn.MaxPool2d()
self.maxpool2 = pass
# Plně propojený lineární výstup nn.Linear(), vstup 16 * 7 * 7, výstup 3 třídy
self.fc1 = pass
def forward(self, x):
# Konvoluce 1
out = pass
# Relu
out = pass
# Max pool 1
out = pass
# Konvoluce 2
out = pass
# Relu
out = pass
# Max pool 2
out = pass
# Změna velikosti - zploštění dat
out = out.view(out.size(0), -1)
# Plně propojený lineární výstup
out = pass
return out
4: Instance třídy modelu¶
In [ ]:
Copied!
# instance modelu
model = pass
# instance modelu
model = pass
In [ ]:
Copied!
# Prarametry modelu
params = [p.numel() for p in model.parameters() if p.requires_grad]
print(params)
# Prarametry modelu
params = [p.numel() for p in model.parameters() if p.requires_grad]
print(params)
5: Inicializace třídy ztráty¶
In [ ]:
Copied!
# Cross-Entropy Loss
criterion = pass
# Cross-Entropy Loss
criterion = pass
6: Inicializace optimalizátoru¶
In [ ]:
Copied!
# optimizer lr= 0.01
learning_rate = pass
# optimalizátor torch.optim.SGD() nebo Adam()
optimizer = pass
# optimizer lr= 0.01
learning_rate = pass
# optimalizátor torch.optim.SGD() nebo Adam()
optimizer = pass
7. Učení modelu¶
In [ ]:
Copied!
# test dataloaderu
pass
x, masks, y = pass
# test dataloaderu
pass
x, masks, y = pass
In [ ]:
Copied!
x = Variable(x)
y = Variable(y)
x = Variable(x)
y = Variable(y)
In [ ]:
Copied!
optimizer.zero_grad()
outputs = model(x)
optimizer.zero_grad()
outputs = model(x)
In [ ]:
Copied!
outputs
outputs
In [ ]:
Copied!
loss = criterion(outputs, y)
loss
loss = criterion(outputs, y)
loss
In [ ]:
Copied!
# Učení
start = time.time()
# epochy trénování
num_epochs = 5
# záznam vývoje ztráty
train_loss, test_loss = [], []
iter = 0
for epoch in range(num_epochs):
for phase in ['train', 'valid']:
if phase == 'train':
model.train(True) # nastavení trénovacího módu
dataloader = train_dataloader
else:
model.train(False) # nastavení evaluačního módu
dataloader = test_dataloader
step = 0
# iterace přes data
for x, masks, y in dataloader:
step += 1
x = Variable(x)
y = Variable(y)
# dopředný chod
if phase == 'train':
# vymazání gradientů
optimizer. pass
# dopředný chod
outputs = pass
# výpočet ztráty (predikce, reference)
loss = pass
# zpětný průchod uvolní paměť grafu backward()
loss. pass
# optimalizace step()
optimizer. pass
else:
# testování
with torch.no_grad():
# dopředný chod
outputs = pass
# výpočet ztráty y.long()
loss = pass
# výpočet přesnosti
# accuracy = acc(outputs, y)
if phase=='train':
train_loss.append(loss)
if step % 10 == 0:
print('Epocha: {} trénovací ztráta: {} '.format(epoch, loss))
else:
test_loss.append(loss)
if step % 10 == 0:
print('Epocha: {} testovací ztráta: {} '.format(epoch, loss))
print('---')
time_elapsed = time.time() - start
print('Trénování dokončeno za {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))
# Učení
start = time.time()
# epochy trénování
num_epochs = 5
# záznam vývoje ztráty
train_loss, test_loss = [], []
iter = 0
for epoch in range(num_epochs):
for phase in ['train', 'valid']:
if phase == 'train':
model.train(True) # nastavení trénovacího módu
dataloader = train_dataloader
else:
model.train(False) # nastavení evaluačního módu
dataloader = test_dataloader
step = 0
# iterace přes data
for x, masks, y in dataloader:
step += 1
x = Variable(x)
y = Variable(y)
# dopředný chod
if phase == 'train':
# vymazání gradientů
optimizer. pass
# dopředný chod
outputs = pass
# výpočet ztráty (predikce, reference)
loss = pass
# zpětný průchod uvolní paměť grafu backward()
loss. pass
# optimalizace step()
optimizer. pass
else:
# testování
with torch.no_grad():
# dopředný chod
outputs = pass
# výpočet ztráty y.long()
loss = pass
# výpočet přesnosti
# accuracy = acc(outputs, y)
if phase=='train':
train_loss.append(loss)
if step % 10 == 0:
print('Epocha: {} trénovací ztráta: {} '.format(epoch, loss))
else:
test_loss.append(loss)
if step % 10 == 0:
print('Epocha: {} testovací ztráta: {} '.format(epoch, loss))
print('---')
time_elapsed = time.time() - start
print('Trénování dokončeno za {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))
Plot training and testing evolution¶
In [ ]:
Copied!
# plt.plot(range(len(train_loss)), [l.item() for l in train_loss], linewidth=0.5)
# plt.plot(range(len(test_loss)), [l.item() for l in test_loss], linewidth=0.5)
# plt.plot(range(len(train_loss)), [l.item() for l in train_loss], linewidth=0.5)
# plt.plot(range(len(test_loss)), [l.item() for l in test_loss], linewidth=0.5)
In [ ]:
Copied!
# plt.plot(range(len(train_loss)), [l.item() for l in train_loss], linewidth=0.5)
# plt.plot(range(len(test_loss)), [l.item() for l in test_loss], linewidth=0.5)
# plt.plot(range(len(train_loss)), [l.item() for l in train_loss], linewidth=0.5)
# plt.plot(range(len(test_loss)), [l.item() for l in test_loss], linewidth=0.5)
In [ ]:
Copied!
# Atd.
# Atd.