https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html
https://colab.research.google.com/drive/1NAXY6ELyNxDHt13nw_cHnBePrsdQTuH-?usp=sharing
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, # 데이터 미리 가져오기 비율
)
<aside> 📌
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개의 메소드만 알면 됨.
# 유저는 코드의 작동 원리를 굳이 몰라도 됨. 유저가 마주하는 건 단순한 사용법이면 됨!
</aside>
<aside> 📌
Parrallel 병렬 처리
장점
단점
TorchText, TorchVision, TorchAudio: 각각 텍스트 데이터셋, 시각 데이터셋, 음성 데이터셋을 갖고 있음
from torchvision import datasets
from torchvision.transforms import ToTensor
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
nn.Linear()
은 1차원 입력만 받을 수 있어서 여기에 데이터 넣으려면 1차원으로 바꿔야 함.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
Loss function
: x축은 (w, b), y축은 loss값. local minimum이나 global minimum을 찾으면, 그게 loss값이 가장 작을 때(== 정답에 가장 가까울 때)ReLu()
입력이 음수면 0 리턴, 입력이 양수면 그대로 리턴
# 위 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)
: 연산을 어떤 하드웨어에서 할 건지 정함. 모델과 데이터가 같은 하드웨어에 있어야 함!