Quickstart — PyTorch Tutorials 2.6.0+cu124 documentation
Note Click here to download the full example code Learn the Basics || Quickstart || Tensors || Datasets & DataLoaders || Transforms || Build Model || Autograd || Optimization || Save & Load Model Quickstart Created On: Feb 09, 2021 | Last Updated: Jan 24,
pytorch.org
샘플 데이터셋 다운받기
torch.utils.data.Dataset
torch.utils.data.DataLoader
- Dataset: 데이터셋의 형태, 데이터셋을 불러오는 방법이 정의되어있음
- DataLoader: 정의된 데이터셋을 학습에 사용하기에 편리하도록 함. batch 단위로 묶어주고, shuffle하거나, 병렬처리 parallel 해주는 wrapper 클래스.
DataLoader( # [DataLoader의 주요 properties]
dataset, # 필수 인자: Dataset 객체
batch_size=1, # 배치 크기
shuffle=False, # 데이터 섞기 여부
num_workers=0, # 병렬 처리를 위한 프로세스 수
drop_last=False, # 마지막 배치가 batch_size보다 작을 때 버릴지 여부
pin_memory=False, # GPU 메모리에 고정할지 여부
collate_fn=None, # 배치를 어떻게 구성할지 커스텀하는 함수
sampler=None, # 데이터 샘플링 방식 지정
batch_sampler=None, # 배치 단위 샘플링 방식 지정
timeout=0, # 데이터 로딩 시 타임아웃 설정
prefetch_factor=2, # 데이터 미리 가져오기 비율
)
📌 Wrapper class 래퍼 클래스
- 개념: 다른 클래스를 감싸서 새로운 기능을 추가하거나, 인터페이스를 변경하는 기능을 하는 클래스
- 다른 클래스를 감싸서 새로운 기능 추가
# 원본 클래스
class Coffee:
def get_cost(self):
return 3000
# 래퍼 클래스
class CoffeeWithMilk:
def __init__(self, coffee):
self.coffee = coffee # 원본 객체를 내부에 저장 -> 기존 기능 사용 가능
def get_cost(self):
return self.coffee.get_cost() + 500 # 새로운 기능 추가할 수 있음
- 인터페이스 변경
# 레거시(기존) 클래스
class OldCalculator:
def add(self, x, y):
return x + y
def subtract(self, x, y):
return x - y
# 새로운 인터페이스를 원하는 상황
# 예: 문자열로 계산식을 받아서 처리하고 싶음
class CalculatorWrapper:
def __init__(self):
self.calculator = OldCalculator()
def calculate(self, expression): # "1 + 2" 같은 문자열을 받음
# 문자열을 파싱
x, op, y = expression.split()
x, y = int(x), int(y)
# 기존 메서드를 새로운 방식으로 사용
if op == '+':
return self.calculator.add(x, y)
elif op == '-':
return self.calculator.subtract(x, y)
# 사용 예시
old_calc = OldCalculator()
print(old_calc.add(1, 2)) # 기존 방식: 유저는 add(), subtract() 2개의
print(old_calc.subtract(4, 2)) # 메소드를 알고 있어야 함.
new_calc = CalculatorWrapper()
print(new_calc.calculate("1 + 2")) # 새로운 방식: 유저는 new_calc()
print(new_calc.calculate("4 - 2")) # 1개의 메소드만 알면 됨.
# 유저는 코드의 작동 원리를 굳이 몰라도 됨. 유저가 마주하는 건 단순한 사용법이면 됨!
📌 Parrallel 병렬 처리
- 장점
- 처리 속도가 빨라짐, CPU 자원을 효율적으로 사용, 대용량 데이터 처리시 유용
- 단점
- 메모리 사용량 증가, 프로세스 간 통신 오버헤드 발생, 디버깅이 더 어려워짐
- 통신 오버헤드: 프로세스들이 데이터를 주고받을 때 발생하는 추가 시간&자원 소모
- TorchText, TorchVision, TorchAudio: 각각 텍스트 데이터셋, 시각 데이터셋, 음성 데이터셋을 갖고 있음
from torchvision import datasets
from torchvision.transforms import ToTensor
Creating Models
class NeuralNetwork(nn.Module): # nn.Module 상속
def __init__(self): # 클래스 초기화
super().__init__() # 부모 클래스 초기화
self.flatten = nn.Flatten() # 평탄화
self.linear_relu_stack = nn.Sequential(
# nn.Linear(input data size, output data size)
# == y = ax + b 선형 변환 (직선만 생성)
nn.Linear(784, 512), # input size == flattened data size
nn.ReLU(), # activatation 함수: 비선형 변환 추가 (곡선 추가)
nn.Linear(512, 512),
nn.ReLU(),
nn.Linear(512, 10) # 아웃풋 클래스(y 라벨)는 총 10개
)
- PyTorch 패키지의 nn.Module 클래스 상속 -> nn.Module에서 정의된 메소드, 프로퍼티 그대로 사용 가능
- super().__init__() : 부모 클래스 nn.Module 초기화 (그냥 정해진 문법임)
- 클래스 초기화 개념이 명확히 이해는 안 됐는데 클래스에게 사용할거라고 미리 신호 줘서 기능들 준비시키는 느낌인듯?
- 초기화를 하지 않으면 정의한 메소드, 프로퍼티가 제대로 작동 안 하고 여러 문제 발생 가능
- 평탄화 Flatten
- 변환 방법: torch.Size([64, 1, 28, 28]) → torch.Size([64, (12828)]) = torch.Size([64, 784])
- 64는 Batch size, 784가 평탄화된 데이터. 기존 3차원 데이터를 1차원 데이터로 바꿈.
- 목적: nn.Linear() 은 1차원 입력만 받을 수 있어서 여기에 데이터 넣으려면 1차원으로 바꿔야 함.
- 변환 방법: torch.Size([64, 1, 28, 28]) → torch.Size([64, (12828)]) = torch.Size([64, 784])
- nn.Linear(784, 512) 계산 방법
# 입력 x: 784개의 값
x = [x1, x2, ..., x784]
# 출력 y: 512개의 값
y = [y1, y2, ..., y512]
# 각각의 출력 y는 모든 입력 x와 연결됨
y1 = w11*x1 + w12*x2 + ... + w1_784*x784 + b1
y2 = w21*x1 + w22*x2 + ... + w2_784*x784 + b2
...
y512 = w512_1*x1 + w512_2*x2 + ... + w512_784*x784 + b512
- w(가중치), b(편향)은 처음에는 랜덤하게 정해지고, 학습하면서 최적화됨
- 첫번째 예측 → 정답 값과 비교했을 때 loss값 계산 → 오차를 줄이는 방향으로 w, b 바꿔감.
- Loss function : x축은 (w, b), y축은 loss값. local minimum이나 global minimum을 찾으면, 그게 loss값이 가장 작을 때(== 정답에 가장 가까울 때)
- 오차 줄이는 방향은 경사하강법 기법 사용! 주로 미니 배치 경사하강법을 사용한다고 함.
# 위 NeuralNetwork 클래스에 이어서...
def forward(self, x): # 실제로 외부에서 호출하는 함수
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
model = NeuralNetwork().to("cpu")
- model.forward(input_data) : 그냥 model() 하면 forward()가 호출된 것으로 간주됨. 굳이 model.forward() 할 필요 없음.
- to(device) : 연산을 어떤 하드웨어에서 할 건지 정함. 모델과 데이터가 같은 하드웨어에 있어야 함!
Optimizing the Model Parameters
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
- Optimizer
- 정의: 파라미터(가중치 w, 편향 b)를 학습하는 방법을 구현한 도구
- 역할: loss 기반으로 파라미터 업데이트, 학습률(Learning rate) 관리, 경사하강법 구현
- 종류: SGD, Adam, …
- lr: Learning rate, 경사하강법에서 한 번에 얼마나 움직일지 정함. 여기서는 0.001 사용
def train(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset)
model.train() # 모델을 학습 모드로 사용
for batch, (X, y) in enumerate(dataloader):
X, y = X.to(device), y.to(device)
# Compute prediction error
pred = model(X)
loss = loss_fn(pred, y)
# Backpropagation
loss.backward() # 역전파 수행. 각 파라미터(w, b)에 대해 gradient(기울기) 계산
# 연쇄법칙 활용해서 미분하는 거 같은데 잘 모르겠음.
optimizer.step() # 계산된 gradient를 활용해서 모델 파라미터 업데이트, 경사하강법 수행
# parameter = parameter - (learning_rate * gradient)
optimizer.zero_grad() # 다음 역전파를 위해 기울기 0으로 초기화.
# 초기화 설정 안 하면 기울기가 계속 누적됨. PyTorch 기본 설정은 기울기 누적임.
if batch % 100 == 0:
loss, current = loss.item(), (batch + 1) * len(X)
print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")
# 순전파 과정
x = 2
w1 = 3 # 첫 번째 가중치
w2 = 4 # 두 번째 가중치
y_target = 10
# 계산 그래프
a = w1 * x # 6
b = w2 * a # 24
loss = (b - y_target)**2 # (24-10)² = 196
loss = ((w2 * (w1 * x)) - y_target) ** 2
= ((w2 * w1 * x) - y_target) ** 2
# 역전파 과정 (연쇄 법칙 사용)
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!")
'AI' 카테고리의 다른 글
PyTorch 스터디 1주차 (0) | 2025.02.23 |
---|---|
정밀도(Precision)와 재현율(Recall)의 차이 (0) | 2024.04.14 |
Keras를 이용한 다중 분류 지도 학습 및 검증 (1) | 2024.03.26 |