파이토치 모델을 정의하기 위해서는 모듈을 상속할 클래스 사용함
- 계층(layer) : 모듈또는 모듈을 구성하는 한 개의 계층. 합성곱층, 선형 계층(linear layer)등
- 모듈(module) : 한 개 이상의 레이어가 모여서 구성된 것
- 모델 : 최종적으로 원하는 네트워크, 한 개의 모듈이 모델이 될 수 있음
모델 파라미터 정의
손실 함수
학습 동안 출력과 실제 값 사이의 오차 측정
- BCELoss : 이진 분류에 사용
- CrossEntropyLoss : 다중 클래스 분류를 위해 사용
- MSELoss : 회귀 모델에서 사용
- 오차 값이 클수록 손실 함수의 값이 큼
- 손실 함수의 값을 최소화하는 가중치와 바이어스를 찾는 것이 학습 목표
옵티마이저
데이터와 손실 함수 바탕으로 모델의 업데이트 방법 결정
- step() 메서드 통해 전달받은 파라미터를 업데이트함
- 모델의 파라미터별로 다른 기준을 적용함
- torch.optim.Optimizer(params, defaults)는 옵티마이저의 기본이 되는 클래스
- zero_grad()는 옵티마이저에 사용된 파라미터들의 기울기(gradient)를 0으로 만듦
- torch.optim.lr_scheduler : 에포크에 따라 학습률 조절 가능
학습률 스케줄러
미리 지정한 횟수의 에포크 지날 때마나 학습률을 감소
학습률 스케줄러를 이용하면 학습 초기에는 빠른 학습 진행하다가 전역 최소점 근처에 다다르면 학습률을 줄여서 최적점을 찾아감
- 전역 최소점(global minimum) : 오차가 가장 작을 때의 값. 최종적으로 찾고자 하는 것. 지역 최소점은 전역 최소점 찾아가는 과정에서 만나는 홀
- 옵티마이저가 지역 최소점에서 학습을 멈추면 최솟값을 갖는 오차를 찾을 수 없는 문제 발생
- optim.lr_scheduler.LamdaLR : 람다 함수를 이용해서 함수의 결과를 학습률로 설정
- optim.lr_scheduler.StepLR : 특정 단계(step)마다 학습률을 감마 비율만큼 감소시킴
- optim.lr_scheduler.MultiStepLR : 지정된 에포크에만 감마 비율로 감소시킴
- optim.lr_scheduler.ExponentialLR : 에포크마다 이전 학습률에 감마만큼 곱함
- optim.lr_scheduler.CosineAnnealingLR : 학습률을 코사인 함수 형태처럼 변화시킴. 학습률이 커지기도하고 작아지기도 함
- optim.lr_scheduler.ReduceLROnPlateau : 학습이 잘 되고 있는지 아닌지에 따라 동적으로 학습률 변화 가능
- 지표(metrics) : 훈련과 테스트 단계를 모니터링함
from torch.optim import optimizer
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer=optimizer,
lr_lambda=lambda epoch : 0.95 ** epoch)
for epoch in range(1, 100+1):
for x, y in dataloader:
optimizer.zero_grad()
loss_fn(model(x), y).backward()
optimizer.step()
scheduler.step()
단순 신경망 정의
nn.Module을 상속받지 않는 매우 단순한 모델 생성 시에 사용함
model = nn.Linear(in_features=1, out_features=1, bias=True)
nn.Module()을 상속해서 정의
- nn.Module을 상속받는 모델은 기본적으로 __init__(), forward()함수를 포함함
- __init__() : 모델에 사용될 모듈(nn.Linear, nn.Conv2d), 활성화 함수 등을 정의
- forward() : 모델에서 실행되어야 하는 연산 정의
class MLP(Module):
def __init__(self, inputs):
super(MLP, self).__init__()
self.layer = Linears(inputs, 1) #계층정의
self.activation = Sigmoid() # 활성화 함수 정의
def forward(self, X):
X=self.layer(X)
X=self.activation(X)
return X
Sequential 신경망 정의
- nn.Sequential을 사용하면 __init__()에서 사용할 네트워크 모델 정의함
- forward() 함수에서 모델에 실행되어야 할 계산 코드로 작성
- 그 안에 포함된 모듈을 순차적으로 실행
- nn.Sequential은 모델의 계층이 복잡할수록 효과가 뛰어남
- model.modules()은 모델 네트워크에 대한 모든 노드 반환
- model.children()은 같은 수준의 하위 노드 반환
import torch.nn as nn
class MLP(Module):
def __init__(self):
super(MLP, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=64, kernel_size=5),
nn.ReLU(inplace=True),
nn.MaxPool2d(2))
self.layer2 = nn.Sequential(
nn.Conv2d(in_channels=64, out_channels=30, kernel_size=5),
nn.ReLU(inplace=True),
nn.MaxPool2d(2))
self.layer3 = nn.Sequential(
nn.Linear(in_features=30*5*5, out_features=10, bias=True),
nn.ReLU(inplace=True))
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = x.view(x.shape[0], -1)
x = self.layer3(x)
return x
model = MLP()
함수로 신경망 정의
- 변수에 저장해둔 계층들을재사용 가능
- 복잡한 모델은 함수보다 nn.Module()을 상속받아 사용하는 것이 편리함
def MLP(in_features=1, hidden_features=20, out_features=1):
hidden = nn.Linear(in_features=in_features, out_features=hidden_features,
bias=True)
activation = nn.ReLU()
output=nn.Linear(in_features=hidden_features, out_features=out_features,
bias=True)
net = nn.Sequential(hidden, activation, output)
return net
모델 훈련
데이터로 모델을 학습시킴
y=wx+b에서 (w,b)의 적절한 값을 찾음
- w,b에 임의의 값 적용해서 전역 최소점에 이를 때까지 파라미터(w,b)를 계속 수정함
1) optimizer.zero_grad() : 기울기를 초기화함
2) loss.backward() : 기울기 값 계산
for epoch in range(100):
yhat = model(x_train)
loss = criterion(yhat, y_train)
optimizer.zero_grad() # 오차가 중첩적으로 쌓이지 않도록 초기화
loss.backward()
optimizer.step()
모델, 손실 함수, 옵티마이저 정의
- 전방향 학습, 기울기 초기화
- 출력 계산 output=model(input)
- 오차 계산 loss=loss_fn(output, target)
- 역전파 학습 loss.backward()
- 기울기 업데이터 optimizer.step()
모델 평가
테스트 데이터셋 사용해서 모델 평가
1. 함수를 이용해서 모델 평가
import torch
import torchmetrics
preds = torch.randn(10,5).softmax(dim=-1)
target = torch.randint(5, (10,))
acc = torchmetrics.functional.accuracy(preds, target)
2. 모듈을 이용해서 모델 평가
import torch
import torchmetrics
metric = torchmetrics.Accuracy() # 모델 평가(정확도) 초기화
n_batches =10
for i in range(n_batches):
preds = torch.randn(10,5).sofrmax(dim=-1)
target = torch.randint(5,(10,))
acc= metric(preds,target)
print(f"Accuracy on batch {i} : {acc}") # 현재 배치에서의 모델 평가 정확도
acc = metric.compute()
print(f"Accuracy on all data : {acc}") # 모든 배치에서의 모델 평가, 정확도
혹은 사이킬런에서 제공하는 혼동 행렬 이용
- confusion_matrix, accuracy_score, classification_report
훈련 과정 모니터링
- 텐서 보드를 사용하면 학습에 사용되는 각종 파라미터 값이 어떻게 변화하는지 시각화 가능, 성능 추적하거나 평가하는 용도 사용 가능
(+ tensorboardX)
1) 텐서 보드를 설정
2) 텐서 보드에 기록
3) 텐서 보드를 사용해서 모델 구조를 살펴봄
import torch
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("../tensorboard") # 모니터링에 필요한 값들이 저장될 위치
for epoch in range(num_epochs):
model.train()
batch_loss =0.0
for i, (x,y) in enumerate(dataloader):
x, y =x.to(device).float(), y.to(device).float()
outputs = model(x)
loss = criterion(outputs, y)
writer.add_scalar("Loss", loss, epoch)
optimizer.zero_grad()
loss.backward()
optimizer.step()
writer.close() # SummaryWriter가 더 필요하지 않으면 close() 매서드 호출
model.train() & model.eval()
- 둘 다 선언해야 모델의 정확도를 높일 수 있음
- model.train() : 훈련 데이터셋에 사용. 모델 훈련이 진행될 것.
드롭아웃(dropout)이 활성화됨
- model.eval() : 모델 평가 시 모든 노드를 사용하겠다는 의미. 검증과 테스트 데이터셋에 사용
model.eval() # 검증 모드로 전환, dropout=False
with torch.no_grad(): # 검증, 테스트에서는 역전파가 필요하지 않아서 기울기 값을 저장하지 않음.
# 기울기 값을 저장하고 기록하는데 필요한 메모리와 연산 시간 줄일 수 있음
valid_loss =0
for x, y in valid_dataloader:
outputs = model(x)
loss = F.cross_entropy(outputs, y.long().squeeze())
valid_loss +=float(loss)
y_hat += [outputs]
valid_loss = valid_loss / len(valid_loader)
'Pytorch' 카테고리의 다른 글
torch.nn과 torch.nn.functional (0) | 2023.09.11 |
---|---|
ResNet Image Feature Extraction (0) | 2023.09.04 |
파이토치 기초 문법 (0) | 2022.04.28 |
파이토치 기초 (0) | 2022.04.27 |
머신러닝과 딥러닝 (0) | 2022.04.26 |