작성자
김명원
일 시
2024. 3. 7 (목) 18:00 ~ 21:00
장 소
복지관 b128-1호
참가자 명단
임혜진, 이재영, 성창민, 김명원, 장원준
사진
파이토치 스터디
https://tutorials.pytorch.kr/beginner/basics/quickstart_tutorial.html
빠른 시작(Quickstart)
파이토치(PyTorch) 기본 익히기|| 빠른 시작|| 텐서(Tensor)|| Dataset과 Dataloader|| 변형(Transform)|| 신경망 모델 구성하기|| Autograd|| 최적화(Optimization)|| 모델 저장하고 불러오기 이번 장에서는 기계 학습의
tutorials.pytorch.kr
코랩을 통해 코드를 실행시켰다.
%matplotlib inline
#notebook을 실행한 브라우저에서 바로 그림을 볼 수 있게 하는 역할
데이터셋(DataSet)은 샘플과 정답을 저장했다.
데이터로더(DataLeader)는 데이터셋을 순회 가능한 객체(데이터를 하나하나씩 처리할 수 있는 객체 )로 감싸는 역할을 한다.
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor
공개 데이터셋에서 학습 데이터와 테스트 데이터를 내려받는다.
Q) 왜 트레이팅 데이터셋과 테스트 데이터가 같지?
A) 각각 train=True와 train=False로 학습 데이터와 테스트 데이터를 분리시킨다.
training_data = datasets.FashionMNIST(
root= "data" ,
train= True ,
download= True ,
transform=ToTensor(),
)
test_data = datasets.FashionMNIST(
root= "data" ,
train= False ,
download= True ,
transform=ToTensor(),
)
데어터셋을 데이터로더의 인자로 전달해 순회 가능한 객체로 감싸고, 자동화된 배치(batch), 샘플링(sampling), 섞기(shuffle) 및 다중 프로세스로 데이터 불러오기(multiprocess data loading)를 지원한다.
즉 데이터로더는 데이터셋에서 원본 데이터를 불러와 모델에서 필요로 하는 형식으로 처리하는 역할을 한다.
batch_size = 64
# 데이터로더를 생성
train_dataloader = DataLoader(training_data, batch_size=batch_size)
test_dataloader = DataLoader(test_data, batch_size=batch_size)
for X, y in test_dataloader:
print ( f "Shape of X [N, C, H, W]: {X.shape} " )
print ( f "Shape of y: {y.shape} {y.dtype} " )
break
결과 : Shape of X [N, C, H, W]: torch.Size([64, 1, 28, 28]) Shape of y: torch.Size([64]) torch.int64
모델 만들기
사용할 CPU나 GPU, MPS 장치를 얻음
# 학습에 사용할 CPU나 GPU, MPS 장치를 얻습니다.
device = (
"cuda"
if torch.cuda.is_available() else "mps"
if torch.backends.mps.is_available()
else "cpu"
)
print( f "Using {device} device" )
결과 : Using cuda device
- CUDA를 지원하는 GPU를 사용중임
파이토치에서 신경망 모델은 nn.Module 을 상속받는 클래스를 생성하여 정의한다.
class NeuralNetwork ( nn . Module ):
def __init__ ( self ):
super(). __init__ ()
self .flatten = nn.Flatten() #1차원으로 변환
self .linear_relu_stack = nn.Sequential( #__init__에서 사용할 네트워크 모델들을 정의, forward() 함수에서 구현될 순전파를 Layer 형태로 가독성이 뛰어나게 코드를 작성할 수 있음
nn.Linear( 28 * 28 , 512 ),
nn.ReLU(),
nn.Linear( 512 , 512 ),
nn.ReLU(),
nn.Linear( 512 , 10 )
)
def forward ( self , x ):
x = self .flatten(x)
logits = self .linear_relu_stack(x)
return logits
model = NeuralNetwork().to(device) #device = cuba로 했음
print(model)
결과 : NeuralNetwork(
(flatten): Flatten(start_dim=1, end_dim=-1)
(linear_relu_stack): Sequential(
(0): Linear(in_features=784, out_features=512, bias=True)
(1): ReLU()
(2): Linear(in_features=512, out_features=512, bias=True)
(3): ReLU()
(4): Linear(in_features=512, out_features=10, bias=True)
)
)
- ReLU함수 사용, 입력값이 0보다 작으면 0으로 반환하고 0보다 크면 입력값을 그대로 반환한다.
모델 매개변수 최적화하기
모델을 학습하려면 손실함수와 옵티마이저가 필요하다.
손실함수 : 머신러닝 혹은 딥러닝 모델의 출력값과 사용자가 원하는 출력값의 오차
옵티마이저 : 딥러닝에서 손실함수를 최적화 해야한다. 이를 수행하는 알고리즘
loss_fn = nn.CrossEntropyLoss() #신경망의 출력과 정수 형태의 타겟(label)을 받아들여서, 해당 출력과 타겟 간의 교차 엔트로피 손실을 계산한다.
optimizer = torch.optim.SGD(model.parameters(), lr= 1e-3 ) #확률적 경사 하강법(SGD) 사용, model.parameters() : 모델의 학습 가능한 파라미터들을 반환하는 함수, lr=1e-3 : 학습률, 파라미터를 얼마나 많이 업데이트할 지를 제어
데이터와 타켓을 모델에 전달해서 예측값을 계산하고 손실함수를 사용하여 타겟 사이의 오차를 계산한다. 이 함수는 주로 반복적으로 호출되어 모델을 여러 에포크(epoch) 동안 학습시키는 데 사용한다.
def train ( dataloader , model , loss_fn , optimizer ):
size = len (dataloader.dataset)
for batch, (X, y) in enumerate (dataloader):
X, y = X.to(device), y.to(device)
# 예측 오류 계산
pred = model(X)
loss = loss_fn(pred, y)
# 역전파
optimizer.zero_grad() #기존의 그라디언트 초기화
loss.backward() #오차에 대한 그라디언트 계산
optimizer.step() #모델의 매개변수 업데이트
if batch % 100 == 0 :
loss, current = loss.item(), (batch + 1 ) * len (X)
print ( f "loss: {loss :>7f } [ {current :>5d } / {size :>5d } ]" )
모델이 학습하고 있는지를 확인하기 위해 테스트 데이터셋으로 모델의 성능을 확인한다.
def test ( dataloader , model , loss_fn ):
size = len (dataloader.dataset)
num_batches = len (dataloader)
model. eval () #모델을 평가 모드로 설정
test_loss, correct = 0 , 0
with torch.no_grad():
for X, y in dataloader:
X, y = X.to(device), y.to(device)
pred = model(X)
test_loss += loss_fn(pred, y).item()
correct += (pred.argmax( 1 ) == y). type (torch. float ). sum ().item()
test_loss /= num_batches
correct /= size
print ( f "Test Error: \n Accuracy: {( 100 *correct) :>0.1f } %, Avg loss: {test_loss :>8f } \n" )
여러번의 반복을 거쳐 수행된다.
epochs = 5
for t in range (epochs):
print ( f "Epoch {t+ 1 } \n-------------------------------" )
train(train_dataloader, model, loss_fn, optimizer)
test(test_dataloader, model, loss_fn)
print ( "Done!" )
결과 - Epoch 5
-------------------------------
loss: 1.338332 [ 64/60000]
loss: 1.325674 [ 6464/60000]
loss: 1.156638 [12864/60000]
loss: 1.264828 [19264/60000]
loss: 1.142240 [25664/60000]
loss: 1.159866 [32064/60000]
loss: 1.185633 [38464/60000]
loss: 1.123085 [44864/60000]
loss: 1.175986 [51264/60000]
loss: 1.088201 [57664/60000]
Test Error: Accuracy: 64.2%, Avg loss: 1.102630
Done!
이상 1주차 스터디를 마무리했다. 파이토치를 활용한 인공지능 개발을 위해 앞으로도 더욱 노력해야 할 것이다. 데이터를 전처리하는 법도 배우고 앞으로도 다양한 기능들을 배워 멋진 모델을 만들어보고 싶다.