[파이토치로 만드는 딥러닝 이론1] nn.Module & nn.Parameter & Backward
2024. 5. 31. 16:45ㆍMOOC
- 기본 구조:
- 모듈(Module): 모든 딥러닝 레이어(층)의 기본 단위다. 이 모듈을 사용해서 데이터가 어떻게 처리되고, 모델이 어떻게 학습할지 정의한다.
- 파라미터(Parameter): 모델이 학습하는 변수들이다. 예를 들어, 데이터의 특성을 기반으로 예측을 할 때 조정되어야 하는 가중치(weight)나 편향(bias) 같은 값들이다.
- 자동 미분(AutoGrad)과 최적화(Optimizer):
- AutoGrad: 모델을 학습할 때 필요한 미분 계산을 자동으로 해주는 도구다. 모델이 어떻게 성능을 개선할지를 계산해준다.
- Optimizer: 계산된 미분 값을 사용하여 모델의 파라미터(가중치, 편향)를 업데이트하고, 이를 통해 모델이 점점 더 좋은 예측을 하도록 돕는다.
실제 코드 예제:
- MyLiner 클래스: 자신만의 선형 레이어를 만드는 예제로, 입력 데이터와 출력 결과 사이의 관계를 학습한다.
- LR 클래스: 로지스틱 회귀 모델을 직접 만들고, 이 모델을 통해 예측과 실제 값 사이의 차이를 줄이는 방법을 구현한다. 여기서는 가중치와 편향을 직접 업데이트하는 과정도 포함된다.
class MyLiner(nn.Module):
def __init__(self, in_features, out_features, bias=True):
super().__init__()
self.in_features = in_features # 입력 특성의 개수
self.out_features = out_features # 출력 특성의 개수
self.weights = nn.Parameter(torch.randn(in_features, out_features)) # 가중치 초기화
self.bias = nn.Parameter(torch.randn(out_features)) # 편향 초기화
def forward(self, x: Tensor):
return x @ self.weights + self.bias # 입력과 가중치의 행렬 곱 및 편향 추가
- __init__ 메소드에서는 입력 및 출력 특성의 수를 정의하고, 가중치와 편향을 nn.Parameter로 초기화하여 학습 가능한 파라미터로 설정한다.
- forward 메소드에서는 입력 x와 가중치의 행렬 곱을 수행하고 편향을 더해 결과를 반환한다.
class LR(nn.Module):
def __init__(self, dim, lr=torch.scalar_tensor(0.01)):
super(LR, self).__init__()
self.w = torch.zeros(dim, 1, dtype=torch.float).to(device) # 가중치를 0으로 초기화
self.b = torch.scalar_tensor(0).to(device) # 편향을 0으로 초기화
self.grads = {"dw": torch.zeros(dim, 1, dtype=torch.float).to(device),
"db": torch.scalar_tensor(0).to(device)} # 그래디언트 초기화
self.lr = lr.to(device) # 학습률
def forward(self, x):
z = torch.mm(self.w.T, x) # 가중치와 입력의 행렬 곱
a = self.sigmoid(z) # 시그모이드 함수 적용
return a
def sigmoid(self, z):
return 1 / (1 + torch.exp(-z)) # 시그모이드 활성화 함수
def backward(self, x, yhat, y):
self.grads["dw"] = (1 / x.shape[1]) * torch.mm(x, (yhat - y).T) # 가중치에 대한 그래디언트 계산
self.grads["db"] = (1 / x.shape[1]) * torch.sum(yhat - y) # 편향에 대한 그래디언트 계산
def optimize(self):
self.w = self.w - self.lr * self.grads["dw"] # 가중치 업데이트
self.b = self.b - self.lr * self.grads["db"] # 편향 업데이트
- __init__ 메소드에서는 모델의 파라미터(가중치와 편향)를 초기화하고, 그래디언트와 학습률도 설정한다.
- forward 메소드에서는 입력에 대한 모델의 예측을 계산한다.
- backward 메소드에서는 예측과 실제 값 사이의 오차로부터 그래디언트를 계산한다.
- optimize 메소드에서는 계산된 그래디언트를 사용하여 모델의 파라미터를 업데이트한다.
Backward의 과정
- Forward Pass:
- 먼저, 모델은 입력 데이터를 받아 순전파를 통해 출력값을 계산한다.
- 예측치와 실제 데이터 간의 손실(오차)가 계산된다.
- Loss 계산:
- 손실 함수(loss function)를 사용하여 예측한 결과값과 실제 결과값 사이의 차이를 수치적으로 나타낸다. 이 손실을 최소화하는 것이 학습의 목표다.
- Backward Pass:
- 계산된 손실 함수의 값에서 출발하여, 파라미터에 대한 손실 함수의 미분값(그래디언트)을 계산한다.
- 이 계산은 연쇄법칙을 사용하는 자동 미분(autograd) 기능을 통해 수행된다.
- 각 레이어와 각 파라미터에 대한 그래디언트가 계산되어 저장된다.
- 파라미터 업데이트:
- Optimizer(최적화 알고리즘)를 사용하여 저장된 그래디언트를 바탕으로 모델의 파라미터를 업데이트한다. 대표적으로 SGD(확률적 경사 하강법)나 Adam 같은 알고리즘이 사용된다.
- optimizer.step() 메소드를 호출하여 각 파라미터를 조정한다.
- 다음 반복(iteration) 또는 에폭(epoch)에 사용하기 전에 optimizer.zero_grad() 메소드를 호출하여 이전 그래디언트를 초기화한다.
예시코드
for epoch in range(epochs):
optimizer.zero_grad() # 그래디언트 버퍼 초기화
outputs = model(inputs) # 모델을 통해 입력에서 출력을 계산
loss = criterion(outputs, labels) # 손실 계산
loss.backward() # 역전파 실행, 각 파라미터에 대한 손실의 그래디언트 계산
optimizer.step() # 파라미터 업데이트
PyTorch Dataset 이론
1. Dataset 클래스
Dataset 클래스는 데이터의 샘플과 레이블을 저장하고 관리하는 역할을 한다. PyTorch에서 Dataset을 사용하려면, 기본적으로 torch.utils.data.Dataset을 상속받은 사용자 정의 클래스를 만들어야 한다. 이 클래스는 주로 다음 세 가지 메소드를 오버라이드(재정의)한다:
import torch
from torch.utils.data import Dataset
class CustomDataset(Dataset):
def __init__(self, text, labels):
self.labels = labels
self.data = text
def __len__(self):
return len(self.labels)
def __getitem__(self, idx):
label = self.labels[idx]
text = self.data[idx]
sample = {"Text": text, "Class": label}
return sample
- __init__: 데이터셋의 초기화를 담당한다. 데이터와 레이블을 로드하고 다른 필요한 초기 설정을 수행한다.
- __len__: 데이터셋의 총 샘플 수를 반환한다. 이는 데이터셋의 길이를 알려주는 함수로 사용된다.
- __getitem__: 인덱스(idx)에 해당하는 샘플을 데이터셋에서 불러와 반환한다. 이 메소드는 데이터셋에서 특정한 하나의 샘플을 가져오는 방법을 정의한다.
2. DataLoader 클래스
DataLoader는 Dataset을 입력으로 받아 이를 배치(batch) 단위로 처리하는 역할을 한다. 이 클래스는 배치 처리, 데이터 셔플링(shuffling), 다중 스레드를 이용한 데이터 로딩 등의 기능을 지원한다. 주요 매개변수는 다음과 같다:
from torch.utils.data import DataLoader
text = ['Happy', 'Amazing', 'Sad', 'Unhappy', 'Glum']
labels = ['Positive', 'Positive', 'Negative', 'Negative', 'Negative']
# Dataset 생성
myDataset = CustomDataset(text, labels)
# DataLoader 설정
myDataLoader = DataLoader(myDataset, batch_size=2, shuffle=True)
# DataLoader를 통해 데이터를 반복하여 출력
for dataset in myDataLoader:
print(dataset)
- batch_size: 한 번에 로드할 데이터 샘플의 수다.
- shuffle: 매 에포크(epoch)마다 데이터를 섞을지의 여부를 결정한다.
- num_workers: 데이터 로딩에 사용할 하위 프로세스의 수다.
출력
{'Text': ['Glum', 'Sad'], 'Class': ['Negative', 'Negative']}
{'Text': ['Unhappy', 'Amazing'], 'Class': ['Negative', 'Positive']}
{'Text': ['Happy'], 'Class': ['Positive']}
'MOOC' 카테고리의 다른 글
[프로젝트로 배우는 데이터사이언스] pima_classification_baseline (1) | 2024.06.27 |
---|---|
PyTorch 프로젝트 구조 이해하기 (0) | 2024.06.06 |
[파이토치로 만드는 딥러닝 이론3] 모델 저장하기 (1) | 2024.06.03 |
[파이토치로 만드는 딥러닝 이론2] PyTorch Dataset 실습 (2) | 2024.06.03 |
[딥러닝] 흉부 엑스레이 이미지 폐렴(PNEUMONIA) 분류 실습 (0) | 2024.05.09 |