Pytorch
에서 모델의 가중치를 저장하기 위해선 3가지 함수만 알면 충분 합니다.
torch.save
: 객체를 디스크에 저장합니다. pickle
모듈을 이용하여 객체를 직렬화 하며, 이 함수를 사용하여 모든 종류의 모델, Tensor 등을 저장할 수 있습니다.torch.load
: pickle
모듈을 이용하여 객체를 역직렬화하여 메모리에 할당합니다.torch.nn.Module.load_state_dict
: 역직렬화된 state_dict를 사용, 모델의 매개변수들을 불러옵니다. state_dict는 간단히 말해 각 체층을 매개변수 Tensor로 매핑한 Python 사전(dict) 객체입니다.간단한 DNN
모델을 통해 연습 해 보겠습니다.
import torch
import torch.nn as nn
x_data = torch.Tensor([
[0, 0],
[1, 0],
[1, 1],
[0, 0],
[0, 0],
[0, 1]
])
y_data = torch.LongTensor([
0, # etc
1, # mammal
2, # birds
0,
0,
2
])
class DNN(nn.Module):
def __init__(self):
super(DNN, self).__init__()
self.w1 = nn.Linear(2, 10)
self.bias1 = torch.zeros([10])
self.w2 = nn.Linear(10, 3)
self.bias2 = torch.zeros([3])
self.relu = nn.ReLU()
self.softmax = nn.Softmax(dim=0)
def forward(self, x):
y = self.w1(x) + self.bias1
y = self.relu(y)
y = self.w2(y) + self.bias2
return y
model = DNN()
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(1000):
output = model(x_data)
loss = criterion(output, y_data)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print("progress:", epoch, "loss=", loss.item())
전체 모델을 저장하거나, 모델의 state_dict
를 저장 할 때 사용합니다.
object
: 저장할 모델 객체path
: 저장할 위치 + 파일명PATH = './weights/'
torch.save(model, PATH + 'model.pt') # 전체 모델 저장
torch.save(model.state_dict(), PATH + 'model_state_dict.pt') # 모델 객체의 state_dict 저장
torch.save({
'model': model.state_dict(),
'optimizer': optimizer.state_dict()
}, PATH + 'all.tar') # 여러 가지 값 저장, 학습 중 진행 상황 저장을 위해 epoch, loss 값 등 일반 scalar값 저장 가능
전체 모델을 불러오거나, 모델의 state_dict
를 불러 올 때 사용합니다.
path
: 불러올 위치 + 파일명state_dict
를 이용하여, 모델 객체 내의 매개 변수 값을 초기화 합니다.
dict
: 불러올 매개 변수 값들이 담겨있는 state_dict
객체model = torch.load(PATH + 'model.pt') # 전체 모델을 통째로 불러옴, 클래스 선언 필수
model.load_state_dict(torch.load(PATH + 'model_state_dict.pt')) # state_dict를 불러 온 후, 모델에 저장
checkpoint = torch.load(PATH + 'all.tar') # dict 불러오기
model.load_state_dict(checkpoint['model'])
optimizer.load_state_dict(checkpoint['optimizer'])
모델을 불러 온 이후에는 이 모델을 학습 할 껀지, 사용 할 껀지에 따라 각각 model.train()
, model.eval()
둘 중에 하나를 사용 하면 됩니다.
모델의 매개변수의 일부만 불러 사용하는 것은 전이학습을 이용할 때 자주 사용합니다. state_dict
의 일부만 불러오거나, 적재하려는 모델보다 더 많은 키를 갖고 있는 state_dict
를 불러 올때는, load_state_dict()
함수의 파라미터에 strict=False
를 입력 해 주면 됩니다.
주의: 위 코드에서는 구현 하지 않은 클래스 입니다.
torch.save(modelA.state_dict(), PATH) # 저장하기
modelB = TheModelBClass(*args, **kwargs) # 불러오기
modelB.load_state_dict(torch.load(PATH), strict=False)
GPU
에서 학습 한 모델과, CPU
에서 학습 한 모델 간 저장하는 방법은 같지만, 케이스에 따라 불러오는 과정이 다릅니다.
저장하는 방법은 다음과 같습니다.
torch.save(model.state_dict(), PATH + 'model.pt')
torch.load()
함수의 map_location
인자에 torch.device('cpu')
를 전달 함으로써, 모델을 동적으로 CPU 장치에 할당합니다.
device = torch.device('cpu')
model = DNN()
model.load_state_dict(torch.load(PATH, map_location=device))
torch.load()
로 초기화 한 모델의 model.to(torch.device('cuda'))
를 호출하여, CUDA Tensor
로 내부 매개변수를 형변환 해 주어야 합니다.
device = torch.device('cuda')
model = DNN()
model.load_state_dict(torch.load(PATH))
model.to(device)
torch.load()
함수의 map_location
인자에 cuda:device_id 를 전달 함으로써, 모델을 동적으로 해당 GPU 장치에 할당합니다. 그 이후에 model.to(torch.device('cuda'))
를 호출, 모델 내의 Tensor
를 CUDA Tensor
로 변환 합니다. 모든 모델 입력에도 .to(torch.device('cuda'))
를 입력하여, CUDA Tensor
로 변환하여야 합니다.
device = torch.device('cuda')
model = DNN()
model.load_state_dict(torch.load(PATH, map_location="cuda:0")) # 사용할 GPU 장치 번호 선택.
model.to(device) # CUDA Tensor 형 변환