2023. 12. 1. 08:52ㆍ머신러닝, 딥러닝/파이토치
◈ AlexNet 사용해서 이미지 분류하기
AlexNet은 2012 이미지넷 경진대회에서 우승한 사전학습 CNN 모델이다. 파이토치를 이용해서 AlexNet을 이용한 이미지 분류를 실시한다. 데이터는 CIFAR 10 데이터를 사용한다.
|
import torch |
|
import torchvision |
|
import torchvision.transforms as transforms |
|
from torch.utils.data import DataLoader |
|
|
|
import torch.nn as nn |
|
import torch.nn.functional as F |
|
import torch.optim as optim |
|
import matplotlib.pyplot as plt |
필요한 라이브러리를 불러온다.
✔ 기본 전처리
|
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) |
|
|
|
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) |
|
trainloader = torch.utils.data.DataLoader(trainset, batch_size=32, shuffle=True) |
|
|
|
testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) |
|
testloader = torch.utils.data.DataLoader(testset, batch_size=32, shuffle=True) |
라인1에서 transforms.Normalize를 이용해서 평균과 표준편차를 따르는 정규분포로 이미지를 표준화한다.
CIFAR 10 이미지는 컬러 이미지이므로 RGB 각 채널마다 표준화를 실시한다. 원래는 학습 데이터의 이미지의 표준과 편차를 사용하지만, 여기서는 모두 평균과 표준편차 모두 0.5로 설정했다.
✔ 모델 구축
|
class AlexNet(nn.Module): |
|
def __init__(self): |
|
super(AlexNet, self).__init__() |
|
self.features = nn.Sequential( |
|
nn.Conv2d(3,64,3), nn.ReLU(), #Conv2d(입력채널수, 출력채널수, 필터 크기) |
|
nn.MaxPool2d(2,2), |
|
nn.Conv2d(64, 192, 3, padding=1), nn.ReLU(), |
|
nn.MaxPool2d(2,2), |
|
nn.Conv2d(192, 384, 3, padding=1), nn.ReLU(), |
|
nn.Conv2d(384, 256, 3, padding=1), nn.ReLU(), |
|
nn.Conv2d(256, 256, 1), nn.ReLU(), |
|
nn.MaxPool2d(2,2)) |
|
|
|
#Dense layer 구축 |
|
self.classifier = nn.Sequential( |
|
nn.Dropout(0.5), |
|
nn.Linear(256*3*3, 1024), nn.ReLU(), |
|
nn.Dropout(0.5), |
|
nn.Linear(1024,512), nn.ReLU(), |
|
nn.Linear(512,10)) |
|
|
|
def forward(self, x): |
|
x = self.features(x) |
|
x = x.view(-1, 256*3*3) |
|
x = self.classifier(x) |
|
return x |
✔ 손실함수 및 최적화방법 정의
|
criterion = nn.CrossEntropyLoss() |
|
alexnet = AlexNet() |
|
optimizer = optim.Adam(alexnet.parameters(), lr=1e-3) |
다중분류에서는 cross entropy 손실함수를 사용하는 경우가 많다. 파이토치에서 제공하는 크로스 엔트로피는 softmax 계산까지 포함되어 있으므로 모델 마지막에 별도로 softmax를 적용하지 않아도 된다.
GPU 연산을 위해서는 모델을 불러올 때 device를 통해서 GPU 연산을 활성화하고, 라인2 뒤에 .to(device)를 반드시 붙여야 한다.
✔ 모델 학습
|
loss_ =[] |
|
|
|
n = len(trainloader) #배치 개수 |
|
|
|
for epoch in range(50): |
|
running_loss = 0.0 |
|
for data in trainloader: |
|
inputs, labels = data[0], data[1] #배치 데이터 |
|
optimizer.zero_grad() |
|
outputs = alexnet(inputs) #예측값 산출 |
|
loss = criterion(outputs, labels) #손실 함수 계산 |
|
loss.backward() #손실 함수 기준으로 역전파 선언 |
|
optimizer.step() #가중치 최적화 |
|
running_loss += loss.item() |
|
|
|
loss_.append(running_loss / n) |
|
print('[%d] loss: %.3f' %(epoch +1, running_loss / len(trainloader))) |
모델을 학습하고 trainset에서 결과를 확인한다.
✔ 학습한 모델을 저장하거나 다시 불러오기
|
#모델 성능이 괜찮다면 추후에 다시 사용하기 위해서 모델을 저장할 수 있음 |
|
PATH = 'C:/Users/Yeong/Desktop/파이토치스터디/Alexnet모델.pth' |
|
torch.save(alexnet.state_dict(),PATH) |
|
|
|
#모델 다시 불러오기 : 해당 모델의 파라미터만 불러오는 것이기 때문에, 모델이 미리 선언되어 있어야 한다. |
|
alexnet = AlexNet() #.to(device) |
|
alexnet.load_state_dict(torch.load(PATH)) |
경로를 설정해서 학습한 모델을 저장한다.
해당 모델을 다시 불러올 때는 alexnet 모델로 학습한 파라미터들을 불러오는 것이기 때문에,
선행적으로 모델이 선언되어야 한다.
✔ 모델 평가
|
correct = 0 |
|
total = 0 |
|
with torch.no_grad(): |
|
alexnet.eval() |
|
for data in testloader: |
|
images, labels = data[0].to(device), data[1].to(device) |
|
outputs = alexnet(images) |
|
_, predicted = torch.max(outputs, 1) |
|
total += labels.size(0) # 개수 누적(총 개수) |
|
correct += (predicted == labels).sum().item() # 누적(맞으면 1, 틀리면 0으로 합산) |
|
|
|
print('Test accuracy: %.2f %%' % (100 * correct / total)) |
라인3에서 평가시에는 requires_grad를 비활성화 한다.
라인4에서 평가 시에는 dropout 과 같은 정규화 작업을 시행하지 않아야 하므로 eval()을 선언한다.
라인8 설명 : p136 추가 참고
◈ Reference
딥러닝을 위한 파이토치 입문, 딥러닝호형 저, 영진닷컴, 2022년 01월 20일
'머신러닝, 딥러닝 > 파이토치' 카테고리의 다른 글
[PyTorch] RNN, LSTM (0) | 2023.12.01 |
---|---|
[PyTorch]신경망으로 회귀분석 / Cross Validation (0) | 2023.12.01 |
[PyTorch] 기본 개념 (0) | 2023.12.01 |