[AI/ML] 미니 배치와 데이터 로더
PyTorch의 DataLoader를 활용한 미니 배치 학습 방식입니다. 메모리 제약을 극복하기 위해 데이터를 작은 단위로 나누어 학습하며, Dataset과 DataLoader를 통해 효율적으로 배치 단위 훈련을 구현합니다.
개요
AI에 대한 기초를 다시 정리하고자 아래 내용을 읽고 정리했습니다.
미니 배치(Mini Batch)
딥러닝 모델들은 훈련하기 위해 수십만 개 이상의 데이터를 사용합니다.
하지만 데이터가 아무리 많아도 데이터를 메모리 공간에 올리는 것엔 물리적인 한계가 존재합니다.
따라서 느린 속도 + 메모리 한계를 극복하기 위해 전체 데이터를 더 작은 단위로 나누어 학습하는데 이를 미니 배치라고 표현합니다. 또한 미니 배치의 사이즈를 배치 크기(batch_size)로 표현합니다.
Epoch
Epoch는 전체 훈련 데이터가 학습에 한 번 사용된 주기입니다.
전체 데이터에서 미니 배치 단위만큼 경사하강법을 수행하고 전체 데이터가 모두 사용되었을 때 1 Epoch입니다.
- 데이터가 2,000개. 미니 배치가 200이라면 미니 배치가 10번 학습되어야 1 Epoch가 성립
- 비용 함수, 경사 하강법은 미니 배치 단위로 수행되는 경우 → 미니 배치 경사 하강법
- 데이터의 일부만 보기에 수렴 과정이 산발적이지만 속도가 빠릅니다.
- 비용 함수, 경사 하강법은 전체 데이터 단위로 수행되는 경우 → 배치 경사 하강법
- 전체 데이터를 사용하므로 가중치 값이 수렴하기에 안정적이지만 느리고 계산량이 많이 필요합니다.
- 비용 함수, 경사 하강법은 미니 배치 단위로 수행되는 경우 → 미니 배치 경사 하강법
이터레이션(Iteration)
미니 배치 경사 하강법을 사용할 때 가중치 업데이트 1회를 의미하는 단어입니다.
- 총 데이터가 2,000개. 배치 사이즈가 200일 때 이터레이션은 10회. 에포크는 1회
데이터 로드하기(DataLoader)
미니 배치 학습을 쉽게 하기 위해 Pytorch 도구를 사용합니다.
- Dataset: 데이터를 저장
- DataLoader: batch 단위로 데이터를 꺼냄
예시에서는 Tensor를 입력받아 저장할 수 있는 TensorDataset을 사용했습니다.
데이터를 불러오는 방법은 다음과 같습니다.
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import TensorDataset # 텐서데이터셋
from torch.utils.data import DataLoader # 데이터로더
x_train = torch.FloatTensor([[73, 80, 75],
[93, 88, 93],
[89, 91, 90],
[96, 98, 100],
[73, 66, 70]])
y_train = torch.FloatTensor([[152], [185], [180], [196], [142]])
dataset = TensorDataset(x_train, y_train)
데이터를 미니 배치 단위로 로드하는 방식은 다음과 같습니다.
- DataLoader는 dataset과 batch_size를 받지만 shuffle 인자도 많이 씁니다.
- shuffle은 데이터 순서를 섞는 것으로 모델이 순서에 익숙해지는 것을 방지합니다.
- 순서에 따라 데이터를 그대로 외우는 것을 방지합니다.
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)
모델과 옵티마이저를 설정합니다.
model = nn.Linear(3,1)
optimizer = torch.optim.SGD(model.parameters(), lr=1e-5)
cost= 비용 값 (예: 10)cost.backward()= 비용을 W로 미분해서 기울기 계산optimizer.step()= 학습률 × 기울기만큼 W를 업데이트기존 가중치 - (학습률 × 기울기)방식으로 정리됩니다.
결과 값은 다음과 같습니다. 조금 더 해석하면 미니 배치 경사하강법으로 Cost(오차)가 흔들리는 것을 확인할 수 있습니다. 또한 최종 가중치는 현재 마지막 Epoch 로 설정됩니다.
만약 가장 좋을 때의 가중치를 저장해두려면 체크포인트(checkpointing, early stopping)로 구성하며 해당 체크포인트를 찾기 위해 검증 데이터(validation)를 사용합니다. 검증 데이터로 해당 체크포인트를 찾아 사용합니다.
Epoch 0/20 Batch 1/3 Cost: 24639.523438
Epoch 0/20 Batch 2/3 Cost: 7149.754395
Epoch 0/20 Batch 3/3 Cost: 3405.706299
Epoch 1/20 Batch 1/3 Cost: 737.025269
Epoch 1/20 Batch 2/3 Cost: 143.452744
Epoch 1/20 Batch 3/3 Cost: 59.147167
Epoch 2/20 Batch 1/3 Cost: 37.379478
Epoch 2/20 Batch 2/3 Cost: 4.725218
Epoch 2/20 Batch 3/3 Cost: 1.797635
Epoch 6/20 Batch 3/3 Cost: 7.471550
Epoch 7/20 Batch 1/3 Cost: 4.698550
Epoch 7/20 Batch 2/3 Cost: 2.714486
Epoch 7/20 Batch 3/3 Cost: 5.062019
Epoch 8/20 Batch 1/3 Cost: 8.113654
...
Epoch 19/20 Batch 3/3 Cost: 6.490381
Epoch 20/20 Batch 1/3 Cost: 1.353482
Epoch 20/20 Batch 2/3 Cost: 3.490023
Epoch 20/20 Batch 3/3 Cost: 6.951240
Epoch를 2,000까지 늘렸을 때 오차가 많이 줄어드는 것을 확인할 수 있습니다.
Epoch 0/2000 Batch 1/3 Cost: 3.120791
Epoch 0/2000 Batch 2/3 Cost: 1.551620
Epoch 0/2000 Batch 3/3 Cost: 2.950326
Epoch 1/2000 Batch 1/3 Cost: 2.076473
Epoch 1/2000 Batch 2/3 Cost: 3.415830
Epoch 1/2000 Batch 3/3 Cost: 0.025309
Epoch 2/2000 Batch 1/3 Cost: 1.973059
Epoch 2/2000 Batch 2/3 Cost: 1.884141
Epoch 2/2000 Batch 3/3 Cost: 4.772414
Epoch 3/2000 Batch 1/3 Cost: 0.561520
Epoch 3/2000 Batch 2/3 Cost: 4.686387
Epoch 3/2000 Batch 3/3 Cost: 4.584628
Epoch 4/2000 Batch 1/3 Cost: 1.699398
Epoch 4/2000 Batch 2/3 Cost: 3.427198
Epoch 4/2000 Batch 3/3 Cost: 2.200335
Epoch 5/2000 Batch 1/3 Cost: 2.005369
Epoch 5/2000 Batch 2/3 Cost: 2.321060
Epoch 5/2000 Batch 3/3 Cost: 7.125224
Epoch 6/2000 Batch 1/3 Cost: 1.354929
Epoch 6/2000 Batch 2/3 Cost: 3.690168
Epoch 6/2000 Batch 3/3 Cost: 3.737782
Epoch 7/2000 Batch 1/3 Cost: 3.450968
Epoch 7/2000 Batch 2/3 Cost: 3.108922
Epoch 7/2000 Batch 3/3 Cost: 3.465338
Epoch 8/2000 Batch 1/3 Cost: 2.713056
...
Epoch 1999/2000 Batch 3/3 Cost: 0.698256
Epoch 2000/2000 Batch 1/3 Cost: 0.126965
Epoch 2000/2000 Batch 2/3 Cost: 0.868454
Epoch 2000/2000 Batch 3/3 Cost: 0.089180
최종 예측 결과입니다.
# 임의의 입력 [73, 80, 75]를 선언
new_var = torch.FloatTensor([[73, 80, 75]])
# 입력한 값 [73, 80, 75]에 대해서 예측값 y를 리턴받아서 pred_y에 저장
pred_y = model(new_var)
print("훈련 후 입력이 73, 80, 75일 때의 예측값 :", pred_y)
# -------------------------------------------------------
훈련 후 입력이 73, 80, 75일 때의 예측값 : tensor([[151.8671]], grad_fn=<AddmmBackward0>)
커스텀 데이터셋(Custom Dataset)
데이터에 따라 커스텀 데이터셋을 만들어 사용할 수 있습니다. 커스텀 데이터셋은 반드시 정의해야하는 메서드가 3개 존재합니다.
__init__: 데이터셋 초기화, 전처리__len__: 총 샘플 개수 리턴 (len(dataset) 할 때 호출)__getitem__: 인덱스로 샘플 1개 가져오기 (dataset[i] 할 때 호출)
class CustomDataset(torch.utils.data.Dataset):
def __init__(self):
def __len__(self):
def __getitem__(self, idx):
DataLoader는 __getitem__ 으로 요소로 batch_size만큼 가져와 미니 배치를 생성합니다.
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import Dataset
from torch.utils.data import DataLoader # 데이터로더
# Dataset 상속
class CustomDataset(Dataset):
def __init__(self):
self.x_data = [[73, 80, 75],
[93, 88, 93],
[89, 91, 90],
[96, 98, 100],
[73, 66, 70]]
self.y_data = [[152], [185], [180], [196], [142]]
# 총 데이터의 개수를 리턴
def __len__(self):
return len(self.x_data)
# 인덱스를 입력받아 그에 맵핑되는 입출력 데이터를 파이토치의 Tensor 형태로 리턴
def __getitem__(self, idx):
x = torch.FloatTensor(self.x_data[idx])
y = torch.FloatTensor(self.y_data[idx])
return x, y
- Dataset 상속
__getitem__x, y 모두 선언해야합니다.
dataset = CustomDataset()
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)
그 외 코드는 동일합니다.
Epoch 0/2000 Batch 1/3 Cost: 18989.921875
Epoch 0/2000 Batch 2/3 Cost: 4662.060059
Epoch 0/2000 Batch 3/3 Cost: 2114.080078
Epoch 1/2000 Batch 1/3 Cost: 415.249969
Epoch 1/2000 Batch 2/3 Cost: 237.831039
Epoch 1/2000 Batch 3/3 Cost: 56.313648
Epoch 2/2000 Batch 1/3 Cost: 20.790310
Epoch 2/2000 Batch 2/3 Cost: 2.807354
Epoch 2/2000 Batch 3/3 Cost: 1.922820
Epoch 3/2000 Batch 1/3 Cost: 4.043968
Epoch 3/2000 Batch 2/3 Cost: 0.226214
Epoch 3/2000 Batch 3/3 Cost: 1.371253
Epoch 4/2000 Batch 1/3 Cost: 3.929478
Epoch 4/2000 Batch 2/3 Cost: 0.128780
Epoch 4/2000 Batch 3/3 Cost: 0.233011
Epoch 5/2000 Batch 1/3 Cost: 0.450442
Epoch 5/2000 Batch 2/3 Cost: 3.518873
Epoch 5/2000 Batch 3/3 Cost: 0.564287
Epoch 6/2000 Batch 1/3 Cost: 0.099612
Epoch 6/2000 Batch 2/3 Cost: 3.317684
Epoch 6/2000 Batch 3/3 Cost: 0.055822
Epoch 7/2000 Batch 1/3 Cost: 2.246110
Epoch 7/2000 Batch 2/3 Cost: 1.809132
Epoch 7/2000 Batch 3/3 Cost: 0.267966
Epoch 8/2000 Batch 1/3 Cost: 3.112362
...
Epoch 1999/2000 Batch 3/3 Cost: 0.545037
Epoch 2000/2000 Batch 1/3 Cost: 1.210260
Epoch 2000/2000 Batch 2/3 Cost: 0.022624
Epoch 2000/2000 Batch 3/3 Cost: 2.050513
훈련 후 입력이 73, 80, 75일 때의 예측값 : tensor([[151.0651]], grad_fn=<AddmmBackward0>)