Getting Started with Pytorch

주제무·2022년 7월 27일
0

파이토치

목록 보기
1/1

Pytorch

Pytorch vs Tensorflow

Define by Run vs Define and Run

Tensorflow
Define and Run

  • 학습 도중에 조건을 바꿀 수 없는, 다르게 표현하면 계산 그래프가 한번 정해지면 입력 데이터만 다르게 할 수 있다.

Pytorch
Define by Run

  • 학습 도중에 조건을 바꿀 수 있는, 학습의 단계마다 새로운 계산 그래프를 정의하여 개선한다.
  • Tensor 연산이 GPU로 가능하다.

Quick Start

datasets vs utils.data.DataLoader

All datasets are subclasses of torch.utils.data.Dataset i.e, they have __getitem__ and __len__ methods implemented. Hence, they can all be passed to a torch.utils.data.DataLoader which can load multiple samples in parallel using torch.multiprocessing workers.

Dataset stores the samples and their corresponding labels, and DataLoader wraps an iterable around the Dataset to enable easy access to the samples.

Ex>
ImageNet 불러오기

imagenet_data = torchvision.datasets.ImageNet('path/to/imagenet_root/')
data_loader = torch.utils.data.DataLoader(imagenet_data,
                                          batch_size=4,
                                          shuffle=True,
                                          num_workers=args.nThreads)

FashionMNIST 불러오기; 밑의 실습은 이 datasets를 이용

# torchvision.datasets을 통해 데이터 로딩
training_data = datasets.FashionMNIST(
                        root='data',
                        train=True,
                        download=True,
                        transform=ToTensor()
)

test_data = datasets.FashionMNIST(
                        root='data',
                        train=False,
                        download=True,
                        transform=ToTensor()
)

참고 : https://pytorch.org/vision/stable/datasets.html

torch.utils.data.Dataset vs tf.data.Dataset(tensorflow)

tensorflow.data.Dataset 은 index로 참조할 수 없다.

ds[0]  # Raising error

하지만 torch.utils.data.Dataset은 index로 참조할 수 있다.

Creating Model

# device를 가져온다
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(f'Using {device} device')

class NeuralNetwork(nn.Module):
  def __init__(self):
    super().__init__()
    self.flatten = nn.Flatten()
    self.linear_relu_stack = nn.Sequential(
                              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()
model = NeuralNetwork().to(device)
print(model)

모델을 생성할 때 device를 지정해준다.
텐서플로우는 keras.Model을 상속받았고
파이토치는 torch.nn.Module을 상속받는다.
하지만 텐서플로우는 Functional API 방식을 권장한다.

nn.Linear --> keras.models.Dense
nn.ReLU --> keras.layers.Activation('relu')

Optimizing the Model Parameters

loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)

Train

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)

    pred = model(X)
    loss = loss_fn(pred, y)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if batch % 100 == 0:
      loss, current = loss.item(), batch * len(X)
      print(f'loss : {loss} [{current/size:>5f}%]')

batch로 묶었기 때문에 data별 총 size --> len(dataloader.dataset)
model.train() --> 모델을 학습 상태로 만든다.
X.to(device) --> device에 올려둔다.

optimizer.zero_grad()
loss.backward()
optimizer.step()

optimizer의 기울기를 단계마다 초기화 하고,
역전파를 통해 Layer의 각 weights loss 계산,
weights를 개선한다.

Test

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")

model.eval() --> 모델을 평가 상태로
with torch.no_grad() --> 학습을 하지 않으므로
loss_fn(pred, y).item() --> loss값을 받기 위해서는 item으로 접근해야 하는 것으로 보인다.

Epochs

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!")

식별하기 쉽게 print문을 작성하고 각 epoch에 학습 결과를 확인한다.

Saving Model

torch.save(model.state_dict(), "model.pth")
print("Saved PyTorch Model State to model.pth")

~/model.pth 저장

Loading Model

model = NeuralNetwork()
model.load_state_dict(torch.load("model.pth"))

keras callback checkpoint와 마찬가지로
일단 Model object를 생성한 후
model.load_state_dict를 통해 모델을 불러온다.

정상적으로 모델을 불러오면 다음의 메세지를 출력한다.

<All keys matched successfully>
classes = [
    "T-shirt/top",
    "Trouser",
    "Pullover",
    "Dress",
    "Coat",
    "Sandal",
    "Shirt",
    "Sneaker",
    "Bag",
    "Ankle boot",
]

model.eval()
x, y = test_data[0][0], test_data[0][1]
with torch.no_grad():
    pred = model(x)
    predicted, actual = classes[pred[0].argmax(0)], classes[y]
    print(f'Predicted: "{predicted}", Actual: "{actual}"')

정리

  • gpu 사용 가능 여부
torch.cuda.is_available()
  • Define Model
class Model(nn.Module):
	def __init__(self):
    	super().__init__()
        pass
        
        
    def forward(self, x):
    	return logits

model = Model().to(device) # device is 'cuda' or 'cpu'
  • loss func & optimizer
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters())
  • train
    X.to(device)
    학습하는 3줄 optimizer, loss
def train(dataloader, model, loss_fn, optimizer):
	model.train()

	for X, y in dataloader:
    	X, y = X.to(device), y.to(device)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
  • test
    model.eval()
    with torch.no_grad()
def test(dataloader, model, loss_fn):
	model.eval()
    
    with torch.no_grad():
    	

참고

https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html

실습 파일 : https://colab.research.google.com/drive/1aEzGNj5XoVeH85ohLNf2y3vsi09CLvoc?usp=sharing

0개의 댓글