Chap3. 간단한 신경망 만들어보기

s2ul3·2022년 10월 3일
0

1. 보스턴 집값예측 : 회귀

1.torch.FloatTensor(A) : 객체 A를 실숫값을 갖는 파이토치 텐서로 변환해주는 함수.
2.torch.nn.MSELoss()(preds,target) : preds와 target에 대한 MSE를 구하는 함수
3. torch.optim.adam.Adam(params, lr) : 학습률 lr을 갖고, 모델의 가중치(params)에 대해 Adam 최적화를 해주는 객체.
4. torch.linspace(A, B, c) : 시작점 A부터 종료점 B까지 데이터 C개를 반환.
코드

2. 손글씨 분류하기 : 다중분류

1. 데이터 살펴보기

from torchvision.datasets.mnist import MNIST
from torchvision.transforms import ToTensor

# ❶ 학습용 데이터와 평가용 데이터 분리
training_data = MNIST(root="./", train=True, download=True, transform=ToTensor())
test_data = MNIST(root="./", train=False, download=True, transform=ToTensor())
  • train = True : 학습용 데이터 불러오기
  • train - False : 평가용 데이터 불러오기
  • transform = ToTensor() : 파이토치 모델의 입력으로는 파이토치 텐서만 이용할 수 있음. 따라서 이미지 파일로 저장되어 있는 데이터를 ToTensor() 함수를 이용하여 파이토치 텐서로 변환해줌.

2. 데이터 불러오기

from torch.utils.data.dataloader import DataLoader

train_loader = DataLoader(training_data, batch_size=32, shuffle=True)

# ❶평가용은 데이터를 섞을 필요가 없음
test_loader = DataLoader(test_data, batch_size=32, shuffle=False) 

Dataloader() :

  • 데이터셋을 원하는 배치크기로 나누어 자동으로 반환하는 메서드
  • Dataloader 객체에 데이터를 넘겨주면--> 원하는 배치크기, shuffle 여부 등을 설정할 수 있다.
  • 학습용 데이터를 shuffle하지 않고 학습하면 하나의 범주만을 출력될 가능성이 있다. --> 학습용 데이터는 학습 전에 shuffle하여 모든 범주의 데이터가 골고루 나오게 해야한다.
  • 평가용 데이터는 데이터를 shuffle할 필요 X

모델 정의 및 학습

import torch
import torch.nn as nn

from torch.optim.adam import Adam

device = "cuda" if torch.cuda.is_available() else "cpu" # ❶ 학습에 사용할 프로세서를 지정

model = nn.Sequential(
   nn.Linear(784, 64),
   nn.ReLU(),
   nn.Linear(64, 64),
   nn.ReLU(),
   nn.Linear(64, 10)
)
model.to(device) # 모델의 파라미터를 GPU로 보냄

lr = 1e-3
optim = Adam(model.parameters(), lr=lr)

for epoch in range(20):
   for data, label in train_loader:
       optim.zero_grad()
       # ❷ 입력 데이터를 모델의 입력에 맞게 모양을 변환
       data = torch.reshape(data, (-1, 784)).to(device)
       preds = model(data)

       loss = nn.CrossEntropyLoss()(preds, label.to(device)) # ❸ 손실 계산
       loss.backward()
       optim.step()

   print(f"epoch{epoch+1} loss:{loss.item()}")

torch.save(model.state_dict(), "MNIST.pth") # ➍ 모델을 MNIST.pth라는 이름으로 저장
  • torch.cudi.is_available() : GPU를 사용할 수 있으면 True, 사용할 수 없으면 False 반환

  • .to(device) : 텐서를 device로 보낸다.

  • torch.reshape(data, shape) : 텐서 data를 shape 모양으로 변형시킨다.
    - shape = (-1,784)인 경우, 여기서 -1에 배치크기가 입력된다.

    • 예를들어, 배치크기가 64인경우, MNIST의 이미지는 28*28 흑백 이미지이므로 입력 텐서는 (64, 28, 28)과 같은 모양을 한다. 이 이미지를 일렬로 펴주기 위해 (-1, 28*28)을 입력하면 -1에 64가 대입되어 최종적으로 (64, 784)같은 모양으로 shape이 바뀐다.
  • torch.nn.CrossEntropyLoss()(preds,target) : preds와 target에 대한 크로스엔트로피 구하는 함수

  • torch.save(A, 경로) : 지정해둔 경로에 객체 A 저장.

  • A.state_dict(pth) : A모델의 가중치를 딕셔너리 형태로 반환한 뒤, pth에 저장

모델 성능 평가

# ❶ 모델 가중치 불러오기
model.load_state_dict(torch.load("MNIST.pth", map_location=device))

num_corr = 0 # 분류에 성공한 전체 개수

with torch.no_grad(): # ❷ 기울기를 계산하지 않음
   for data, label in test_loader:
       data = torch.reshape(data, (-1, 784)).to(device)

       output = model(data.to(device))
       preds = output.data.max(1)[1] # ❸ 모델의 예측값 계산
       # ❹ 올바르게 분류한 개수
       corr = preds.eq(label.to(device).data).sum().item()
       num_corr += corr

   print(f"Accuracy:{num_corr/len(test_data)}") # 분류 정확도를 출력합니다.
  • model.load_state_dict(torch.load("MNIST.pth", map_location=device)) : 모델파일을 불러온다.
    - map_location : 불러올 위치를 말하는데 기본적으로 CPU에 불러오지만 원하는 장치에 불러올 수 있다. GPU를 갖고 있다면 GPU에, 없다면 CPU에 불러옴.
  • no_grad() : 기울기 계산 X, 학습할 때는 가중치를 업데이트하는데 기울기가 필요하지만, 평가는 가중치를 바꿀 필요 없으므로 기울기 계산 X
  • max(1)[1] : 가장 높은 값을 갖는 위치 반환.
    - 모든 텐서의 차원은 배치, 클래스 순서.
    • max(0)은 배치에서 가장 높은 값을 , max(1)은 클래스 차원에서 가장 높은 값을 반환한다는 뜻.
      - max()는 최대 예측값, 최대 예측값의 인덱스를 묶어서 리스트로 반환하므로 max(1)[1]은 모든 배치에 대해 가장 높은 클래스값을 갖는 인덱스만을 가져온다.
  • eq() : 값이 같으면 1, 다르면 0을 반환.
    코드
profile
statistics & computer science

0개의 댓글