[AITech] 20220127 - PyTorch 모델 불러오기

2 minute read


학습 내용 정리

모델 불러오기

요즘 딥러닝에서는 좋은 성능을 보이는 Backbone 모델(VGG, ResNet, BERT 등)을 가져와 본인의 데이터 셋으로 Transfer learning(Fine Tuning)시키는 과정이 일반적이다.

또한 본인의 모델을 다른 사람들과 공유하고 싶을 수도 있다.

이런 경우에, 모델 또는 파라미터를 파일로 저장할 수 있다.

Save

  • torch.save(model, path)

    • 사용 목적
      • 모델 자체(+파라미터) 또는 파라미터만을 저장
      • 모델 학습 중간 과정의 저장을 통해 가장 좋은 성능을 보이는 모델을 선택(EarlyStopping)
      • 만들어진 모델을 외부 연구자와 공유하여 학습 재연성 향상
    • 예시 코드
    '''모델의 파라미터만!'''
    for param_tensor in model.state_dict(): # state_dict: 모델의 파라미터를 표시
        print(param_tensor, "\t", model.state_dict()[param_tensor].size())
    '''
    Model's state_dict:
    layer1.0.weight 	 torch.Size([16, 3, 3, 3])
    layer1.0.bias 	 torch.Size([16])
    layer1.1.weight 	 torch.Size([16])
    layer1.1.bias 	 torch.Size([16])
    layer1.1.running_mean 	 torch.Size([16])
    layer1.1.running_var 	 torch.Size([16])
    layer1.1.num_batches_tracked 	 torch.Size([])
    layer2.0.weight 	 torch.Size([32, 16, 3, 3])
    layer2.0.bias 	 torch.Size([32])
    layer2.1.weight 	 torch.Size([32])
    layer2.1.bias 	 torch.Size([32])
    layer2.1.running_mean 	 torch.Size([32])
    layer2.1.running_var 	 torch.Size([32])
    layer2.1.num_batches_tracked 	 torch.Size([])
    layer3.0.weight 	 torch.Size([64, 32, 3, 3])
    layer3.0.bias 	 torch.Size([64])
    layer3.1.weight 	 torch.Size([64])
    layer3.1.bias 	 torch.Size([64])
    layer3.1.running_mean 	 torch.Size([64])
    layer3.1.running_var 	 torch.Size([64])
    layer3.1.num_batches_tracked 	 torch.Size([])
    fc1.weight 	 torch.Size([1000, 576])
    fc1.bias 	 torch.Size([1000])
    fc2.weight 	 torch.Size([1, 1000])
    fc2.bias 	 torch.Size([1])
    '''
          
    torch.save(model.state_dict(), # 모델의 파라미터를 저장
              os.path.join(MODEL_PATH, "model.pt"))
      
    new_model = TheModelClass()
    new_model.load_state_dict(torch.load(os.path.join(MODEL_PATH, "model.pt"))) # 같은 형태의 모델에서 파라미터만 load
      
    '''모델의 구조 전체!'''
    torch.save(model, os.path.join(MODEL_PATH, "model.pt")) # 모델 구조 save
    model = torch.load(os.path.join(MODEL_PATH, "model.pt")) # 모델 구조 load
    

    모델 구조 살펴보기: torchsummary.summary

    from torchsummary import summary
    summary(model, (3,224,224))
    '''
    ----------------------------------------------------------------
            Layer (type)               Output Shape         Param #
    ================================================================
                Conv2d-1         [-1, 16, 111, 111]             448
           BatchNorm2d-2         [-1, 16, 111, 111]              32
                  ReLU-3         [-1, 16, 111, 111]               0
             MaxPool2d-4           [-1, 16, 55, 55]               0
                Conv2d-5           [-1, 32, 27, 27]           4,640
           BatchNorm2d-6           [-1, 32, 27, 27]              64
                  ReLU-7           [-1, 32, 27, 27]               0
             MaxPool2d-8           [-1, 32, 13, 13]               0
                Conv2d-9             [-1, 64, 6, 6]          18,496
          BatchNorm2d-10             [-1, 64, 6, 6]             128
                 ReLU-11             [-1, 64, 6, 6]               0
            MaxPool2d-12             [-1, 64, 3, 3]               0
              Dropout-13                  [-1, 576]               0
               Linear-14                 [-1, 1000]         577,000
               Linear-15                    [-1, 1]           1,001
    ================================================================
    Total params: 601,809
    Trainable params: 601,809
    Non-trainable params: 0
    ----------------------------------------------------------------
    Input size (MB): 0.57
    Forward/backward pass size (MB): 5.53
    Params size (MB): 2.30
    Estimated Total Size (MB): 8.40
    ----------------------------------------------------------------
    '''
    

Checkpoints

  • Checkpoints

    • 사용 목적

      • 학습의 결과물(loss, metric 등)을 저장하며 최선의 결과를 선택
      • 일반적으로 epoch, loss, metric을 함께 저장하여 확인
      • colab에서 지속적인 학습을 위해 필요
    • 예시 코드

      for e in range(1, EPOCHS+1):
          epoch_loss = 0
          epoch_acc = 0
          for X_batch, y_batch in dataloader:
              X_batch, y_batch = X_batch.to(device), y_batch.to(device).type(torch.cuda.FloatTensor)
                  
              optimizer.zero_grad()        
              y_pred = model(X_batch)
                         
              loss = criterion(y_pred, y_batch.unsqueeze(1))
              acc = binary_acc(y_pred, y_batch.unsqueeze(1))
                  
              loss.backward()
              optimizer.step()
                  
              epoch_loss += loss.item()
              epoch_acc += acc.item()
                  
                  
          torch.save({
              'epoch': e,
              'model_state_dict': model.state_dict(),
              'optimizer_state_dict': optimizer.state_dict(),
              'loss': epoch_loss,
              }, f"saved/checkpoint_model_{e}_{epoch_loss/len(dataloader)}_{epoch_acc/len(dataloader)}.pt")
                  
          
          print(f'Epoch {e+0:03}: | Loss: {epoch_loss/len(dataloader):.5f} | Acc: {epoch_acc/len(dataloader):.3f}')
      

Pretrained model Transfer learning

  • Pretrained model Transfer learning

    • 사용 목적

      • 일반적으로 대용량 데이터셋으로 만들어진 모델의 성능이 좋다.
      • 성능이 좋은 모델을 가져와 본인의 데이터셋으로 재학습
      • backbone architecture가 잘 학습된 모델에서 일부분만 변경하여 학습을 수행(freezing)
      • 현재의 DL에서 가장 일반적인 학습 방법
    • 참고 사이트

    • 예시 코드

      from torch import nn
      from torchvision import models
          
      class MyNewNet(nn.Module):   
          def __init__(self):
              super(MyNewNet, self).__init__()
              self.vgg19 = models.vgg19(pretrained=True) # pretrained vgg model
              self.linear_layers = nn.Linear(1000, 1)    # 본인의 목적에 맞게 layer를 추가
          
          
          # Defining the forward pass    
          def forward(self, x):
              x = self.vgg19(x)        
              return self.linear_layers(x)
              
              
      for param in my_model.parameters(): # freezing layers
          param.requires_grad = False
      for param in my_model.linear_layers.parameters(): # 마지막 layer만 학습 수행
          param.requires_grad = True
      


Leave a comment