카테고리 없음

[torch.nn-(3)]

개발도사(진) 2023. 12. 16. 00:39

앞선 포스팅에서 training model을 만들고, 그 training set을 torch.nn의 여러 기능을 이용해 좀 더 쉽고 성능 좋게 개선하는 방법을 알아보았다. 이번 포스팅에서는 dataset(x_train, y_train 등) 을 다루는 방법, gpu 사용을 통해 성능을 개선하는 방법을 알아본다.

 

Refactor using Dataset - (1)

기본적인 tutorial에서 제공하는 방식이다. 먼저, torch.util.data로부터 TensorDataSet을 import한다.

from torch.utils.data import TensorDataset

 

 

 

import tensorflow as tf

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

x_train = torch.tensor(x_train.reshape(60000, 784)/255, dtype=torch.float32)
x_test = torch.tensor(x_test.reshape(10000, 784)/255, dtype=torch.float32)

y_train = torch.tensor(y_train, dtype=torch.long)
y_test = torch.tensor(y_test, dtype=torch.int64)

앞서 우리는 위와 같은 code로 training에 필요한 dataset을 가져오고 또 reshape하였다. 이제 여기에 TensorDataSet을 사용하여 x_train, y_train을 묶어서 train_ds라는 변수에 할당한다.

train_ds = TensorDataset(x_train, y_train)

이제 기존 code에서 xs, ys를 직접 idx를 통해 가져왔던 것을 다음 코드 한 줄로 대체할 수 있다. 

idx = torch.randint(len(x_train), (batch_size,))
xs, ys = train_ds[idx]

#기존 코드
#xs = x_train[idx]
#ys = y_train[idx]
#

 

Refactor using Dataset - (2)

앞서 소개한 방법은 dataset을 약간 더 편하게 다룰 수 있는 것 이외에 큰 개선점이 없었다. 이번에는 torch.utils.data.Dataset을 활용하여 class를 만드는 방식으로 dataset을 다루는 방법을 개선한다. 보다 정확히는, 어떠한 dataset을 우리가 원하는 형식으로 다룰 수 있도록, 그 토대가 되는 class를 만드는 것이 목표이다.

class MyDataset(torch.utils.data.Dataset): 
    def __init__(self, data):
        self.data = data

    def __getitem__(self, idx): 
        x = self.data[0][idx]
        y = self.data[1][idx]

        return x, y

    def __len__(self):
        return len(self.data[0])
  • __init__(self, data): class의 constructor. 생성 시 매개변수로 받는 data를 이 class의 member 변수 data로 지정한다.
  • __getitem__(self, idx): data의 각 Item에서 매개변수로 주어진 index의 값을 가져온다. 우리는 x_train(test), y_train(test)을 사용할 것이기 때문에 위와 같이 구현하였다.
  • __len__(self): dataset의 길이 파악. data[0]을 사용하기 때문에 여기서는 x_train의 길이를 반환한다.

Refactor using DataLoader

앞서 training을 진행할 때 training은 목표 dataset을 대상으로 batch 단위로 진행된다는 것을 언급하였는데, DataLoader를 사용하여 training dataSet을 어떤 batch 단위로 training 시킬지 지정할 수 있다. 사용법은 아래와 같다. 

from torch.utils.data import DataLoader
train_ds = MyDataSet((x_train,y_train))
train_dl = DataLoader((train_ds, batch_size=10))
#batch_size = 10
#train_dl = DataLoader((train_ds, batch_size))

 

포스팅 [torch.nn-(1)] 부터 여기까지 진행한 결과 최종 코드는 아래와 같다.

model = MyModel()
optimizer = optim.Adam(params=model.parameters(), lr=lr)

for epoch in range(epoch):
    for xb, yb in train_dl: 
        pred = model(xb)
        loss = loss_func(pred, yb)

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

print(loss_func(model(xb), yb))

 

그러나 Colab의 기본 CPU 모드에서 사용하기에 이 코드는 너무 느리다. Google colab은 사용자가 하드웨어 가속기를 이용할 수 있도록 지원하기 때문에, 해당 기능을 이용하여 학습 속도를 높힐 수 있다. 

 

Colab의 기본 설정은 CPU로 되어 있는데, 런타임>런타임 유형 변경을 통해 그 설정을 변경할 수 있다. 이번 포스팅에서는 TPU(TPU-구글이 제공하는 Tensor Processing Unit)을 사용하였고, 위 최종 코드를 수행한 결과는 아래와 같다.