딥러닝 튜토리얼에 등장하는 FashionMNIST 데이터 셋을 통해서
Tensorflow.Keras 와 PyTorch 모델링의 차이점을 정리해 보았습니다.
모델 정의
* 이해를 돕기 위해 subclass 형식으로 모델을 정의하였습니다.
Tensorflow.Keras
tf.debugging.set_log_device_placement(True)
class MyModel(tf.keras.Model):
def __init__(self):
super(MyModel,self).__init__()
self.flatten = tf.keras.layers.Flatten(input_shape=(28,28))
self.fc1 = tf.keras.layers.Dense(512,activation='relu')
self.dropout = tf.keras.layers.Dropout(0.2)
self.fc2 = tf.keras.layers.Dense(10, activation='softmax')
def call(self,inputs):
x = self.flatten(inputs)
x = self.fc1(x)
x = self.dropout(x)
x = self.fc2(x)
return x
model = MyModel()
PyTorch
# Get cpu or gpu device for training.
device = "cuda" if torch.cuda.is_available() else "cpu"
# Define model
class NeuralNetwork(nn.Module):
def __init__(self):
super(NeuralNetwork, self).__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().to(device)
모델 정의 시 차이점을 비교해 보겠습니다.
GPU 할당 | 상속 클래스 | fully connected layer | 순방향 계산 함수명 | 모델 인스턴스 할당 | |
PyTorch | cuda.is_available() | nn.Module | nn.Linear | call() | model.to(device) |
Tensorflow | 자동 | keras.Model | keras.layers.Dense | forward() | model() |
*Tensorflow는 tf.debugging.set_log_device_placement(True) 코드를 통해서
어디에 할당되어있는지를 확인할 수 있습니다.
PyTorch는 GPU 탑재 여부를 담은 변수 device를 모델 객체에 할당할 때 포함시킵니다.
model = NeuralNetwork().to(device)
모델 컴파일
Tensorflow.keras
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
PyTorch
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
Tensorflow는 정의한 모델 객체의 complile 메서드를 통해서 optimizer , loss function , metrics를 정의합니다.
PyTorch는 optimizer , loss function 변수에 저장하고 학습 함수에서 직접 사용합니다.(뒤에 설명)
모델 학습
Tensorflow.keras
model.fit(train_images, train_labels, epochs=5)
PyTorch
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)
# Compute prediction error
pred = model(X)
loss = loss_fn(pred, y)
# Backpropagation
optimizer.zero_grad()
loss.backward()
optimizer.step()
if batch % 100 == 0:
loss, current = loss.item(), batch * len(X)
print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")
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")
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!")
차이점은 모델 학습 부분에서 가장 큰 차이를 보입니다.
tensorflow 는 fit() 함수로 간단하게 학습을 사용할 수 있습니다.
반면에 PyTorch는 함수 속 for 문을 정의하여 모델 학습(train)과 검증(test) 코드를 구현해야 합니다.
PyTorch가 구현하기 어렵지만 더욱더 직관적이고 학습하기 용이합니다.
optimizer.zero_grad() : Gradient를 초기화합니다.
loss.backward() : Loss를 기준으로 Gradient를 저장합니다.
optimizer.step() : 파라미터(weight) 업데이트.
참고 : https://algopoolja.tistory.com/55
실제 학습과정이 머릿속에 그려짐 but 복잡함.
물론 tensorflow 의 keras처럼 pytorch_lightning이 등장하여 쉽게 구현할 수도 있습니다.
하지만 딥러닝의 과정을 공부하기에는 Torch를 사용하고 익숙해지는 것이 더 도움이 될 것 같습니다.
어려운 것을 알고 쉬운 것을 하는 건 문제가 되지않지만.
쉬운 것을 먼저하면 어려운 것을 할때 문제가 됩니다.
'Machine learning > Deep Learning' 카테고리의 다른 글
[PyTorch]. Dataset 과 Dataloader 사용하여 전처리하기 (1) | 2021.09.21 |
---|---|
[DeepLearning]. GPU 메모리와 배치사이즈(Batch_size)의 관계 (0) | 2021.09.16 |
[Deep Learning] Tensorflow 자주 사용하는 Tensor 함수 정리 (0) | 2021.08.21 |
[Deep Learning] Weight Initialization(기울기 초기화), Xavier , He (0) | 2021.08.17 |
[Deep Learning] Activation Function ( 활성화 함수 ) - 비선형 함수(non linear function ) (0) | 2021.08.17 |