๋ฅ๋ฌ๋(10) - AlexNet
๐ฉ๐ป AlexNet
๐๐ CNN ๊ตฌ์กฐ ํฑ์๋ณด๊ธฐ
- 3์ฐจ์ ๊ตฌ์กฐ
- ๋๋น(width)์ ๋์ด(height)๋ฟ๋ง ์๋๋ผ ๊น์ด(depth)๋ฅผ ๊ฐ๋๋ค.
- ์ด๋ฏธ์ง๋ R/G/B ์ฑ๋ถ ์ธ ๊ฐ๋ฅผ ๊ฐ๊ธฐ ๋๋ฌธ์ ์์์ด 3์ด์ง๋ง, ํฉ์ฑ๊ณฑ์ ๊ฑฐ์น๋ฉด์ ํน์ฑ ๋งต์ด ๋ง๋ค์ด์ง๊ณ ์ด๊ฒ์ ๋ฐ๋ผ ์ค๊ฐ ์์์ ๊น์ด๊ฐ ๋ฌ๋ผ์ง๊ฒ ๋๋ค. (3์์ ๋ ์ปค์ง์๋ ์์)
๐ AlexNet์ ๊ตฌ์กฐ
- ํฉ์ฑ๊ณฑ์ธต ์ด ๋ค์ฏ ๊ฐ + ์์ ์ฐ๊ฒฐ์ธต ์ธ ๊ฐ
- ๋งจ ๋ง์ง๋ง ์์ ์ฐ๊ฒฐ์ธต์ ์นดํ ๊ณ ๋ฆฌ 1000๊ฐ๋ฅผ ๋ถ๋ฅํ๊ธฐ ์ํด ์ํํธ๋งฅ์ค ํ์ฑํ ํจ์๋ฅผ ์ฌ์ฉํจ
- GPU ๋ ๊ฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ๋ณ๋ ฌ ๊ตฌ์กฐ ์ด๋ค.
- ๋คํธ์ํฌ ์ ๋ ฅ :
๋ชฉํํ๋ ์ฝ๋์ ๋ํ ๋คํธ์ํฌ ์ค๊ณ
- GPU-1์์๋ ์ฃผ๋ก ์ปฌ๋ฌ์ ์๊ด์๋ ์ ๋ณด๋ฅผ ์ถ์ถํ๊ธฐ ์ํ ์ปค๋์ด ํ์ต๋๊ณ , GPU-2์์๋ ์ฃผ๋ก ์ปฌ๋ฌ์ ๊ด๋ จ๋ ์ ๋ณด๋ฅผ ์ถ์ถํ๊ธฐ ์ํ ์ปค๋์ด ํ์ต๋๋ค.
โ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํธ์ถํ๊ธฐ
import torch
import torchvision
from torch.utils.data import DataLoader, Dataset
from torchvision import transforms
from torch.autograd import Variable
from torch import optim
import torch.nn as nn
import torch.nn.functional as F
import os
import cv2
import random
from PIL import Image
from tqdm import tqdm_notebook as tqdm
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
โ ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌํ๊ธฐ
- ์์์ ์ค๋ช ์ ํ๊ธฐ ๋๋ฌธ์ ๊ตณ์ด ์ค๋ช ์ ์ฒจ๋ถํ์ง ์๊ฒ ๋ค.
๋ 6-23 ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
class ImageTransform():
def __init__(self, resize, mean, std):
self.data_transform = {
'train': transforms.Compose([
transforms.RandomResizedCrop(resize, scale=(0.5,1.0)),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize(mean, std)
]),
'val': transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(resize),
transforms.ToTensor(),
transforms.Normalize(mean, std)
])
}
def __call__(self, img, phase):
return self.data_transform[phase](img)
โ ์ด๋ฏธ์ง๊ฐ ์์นํ ๊ฒฝ๋ก์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ ํ๋ จ, ๊ฒ์ฆ ,ํ ์คํธ๋ก ๋ถ๋ฆฌํ๊ธฐ
cat_directory = '/cat'
dog_directory = '/dog'
cat_images_filepaths = sorted([os.path.join(cat_directory, f) for f in os.listdir(cat_directory)])
dog_images_filepaths = sorted([os.path.join(dog_directory, f) for f in os.listdir(dog_directory)])
images_filepaths = [*cat_images_filepaths, *dog_images_filepaths]
correct_images_filepaths = [i for i in images_filepaths if cv2.imread(i) is not None]
random.seed(42)
random.shuffle(correct_images_filepaths)
train_images_filepaths = correct_images_filepaths[:400]
val_images_filepaths = correct_images_filepaths[400:-10]
test_images_filepaths = correct_images_filepaths[-10:]
print(len(train_images_filepaths), len(val_images_filepaths), len(test_images_filepaths))
โ ์ปค์คํ ๋ฐ์ดํฐ์ ์ ์ ์ํ๊ธฐ
class DogvsCatDataset(Dataset):
def __init__(self, file_list, transform=None, phase='train'):
self.file_list = file_list #์ด๋ฏธ์ง ๋ฐ์ดํฐ๊ฐ ์์นํ ํ์ผ ๊ฒฝ๋ก
self.transform = transform #์ด๋ฏธ์ง ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
self.phase = phase #self.phase๋ ImageTransform()์์ ์ ์ํ ‘train’๊ณผ ‘val’์ ์๋ฏธ
def __len__(self):
return len(self.file_list)
def __getitem__self(self, idx):
img_path = self.file_list[idx] #์ด๋ฏธ์ง ๋ฐ์ดํฐ์ ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ ธ์ค๊ธฐ
img = Image.open(img_path)
img_transformed = self.transform(img, self.phase)
label = img_path.split('/')[-1].split('.')[0] #๋ ์ด๋ธ ๊ฐ ๊ฐ์ ธ์ค๊ธฐ
if label == 'dog':
label = 1
elif label == 'cat':
label = 0
return img_transformed, label # ์ ์ฒ๋ฆฌ๊ฐ ์ ์ฉ๋ ์ด๋ฏธ์ง์ ๋ ์ด๋ธ์ ๋ฐํํจ
โ ๋ณ์ ์ ์ํ๊ธฐ(ํ๊ท , ํ์คํธ์ฐจ, ๋ฐฐ์น์ฌ์ด์ฆ, ์ด๋ฏธ์ง ๋ฐ์ดํฐ ์ฌ์ด์ฆ)
size = 256 #AlexNet์ ๊น์ด๊ฐ ๊น์ ๋คํธ์ํฌ๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ์ด๋ฏธ์ง ํฌ๊ธฐ๊ฐ 256์ด ์๋๋ฉด ํ๋ง์ธต ๋๋ฌธ์ ํฌ๊ธฐ๊ฐ ์ค์ด ์ค๋ฅ ๋ฐ์
mean = (0.485, 0.456, 0.406)
std = (0.229, 0.224, 0.225)
batch_size = 32
โ AlexNet ๋ชจ๋ธ ๋คํธ์ํฌ ์ ์ํ๊ธฐ
class AlexNet(nn.Module):
def __init__(self) -> None:
super(AlexNet, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(64, 192, kernel_size=5, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(192, 384, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(384, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
)
self.avgpool = nn.AdaptiveAvgPool2d((6, 6))
self.classifier = nn.Sequential(
nn.Dropout(),
nn.Linear(256*6*6, 4096),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(4096, 512),
nn.ReLU(inplace=True),
nn.Linear(512, 2),
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
x = self.features(x)
x = self.avgpool(x)
x = torch.flatten(x, 1)
x = self.classifier(x)
return x
nn.ReLU(inplace=True)์ inplace=True
- ์ฐ์ฐ์ ๋ํ ๊ฒฐ๊ด๊ฐ์ ์๋ก์ด ๋ณ์์ ์ ์ฅํ๋ ๊ฒ์ด ์๋ ๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ ๋์ฒดํ๋ ๊ฒ์ ์๋ฏธ
- ๊ธฐ์กด ๊ฐ์ ์ฐ์ฐ ๊ฒฐ๊ด๊ฐ์ผ๋ก ๋์ฒดํจ์ผ๋ก์จ ๊ธฐ์กด ๊ฐ๋ค์ ๋ฌด์ํจ
ํ๋ง์ธต
nn.AvgPool2d
- (N, C, Hin, Win) ํฌ๊ธฐ์ ์ ๋ ฅ์ (N, C, Hout, Wout) ํฌ๊ธฐ๋ก ์ถ๋ ฅํ๋ ๊ฒ
- Hout, Wout ๊ณ์ฐํ๊ธฐ
AdaptiveAvgPool2d
- ํ๋ง ์์ ์ด ๋๋ ๋ ํ์ํ ์ถ๋ ฅ ํฌ๊ธฐ๋ฅผ ์ ์