ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [08.26 P Stage Day4] - 📝 Training & Inference
    네이버 부스트캠프 AI Tech 2기 2021. 8. 28. 19:10
    728x90
    반응형

    모델 훈련(Train) 과 Inference

    • 요소

    Loss

    : Loss 함수 = Cost 함수 = Error 함수, Backpropagation을 진행할 때, Output과 Target 값을 가지고 Loss 값을 구할 때 사용하는 함수이다.

    • nn.Loss 패키지에서 확인할 수 있다.Loss 함수 또한 forward 함수를 가지고 있기 때문에, Model과 연결되어 학습이 진행된다.
    • loss.backward()
    • 재미있는 것은 net이라는 Model에서 output이 만들어 지고, output과 label 값을 통해서 Loss 값을 구해준다. 또한 중요한 사실은, forward 함수를 통해서 Model 부터 loss 과정 전체가 Chain 으로 연결이 된다.
    • : 이 함수가 실행되면 모델의 파라미터의 grad 값이 업데이트가 된다.
    • Focal Loss, Label SmoothingLabel Smoothing Loss : Class Target Label을 Onehot 표현하기 보다 조금 Soft하게 표현해서 일반화 성능을 높이기 위한 것이다.
    • Focal Loss : Class Imbalance 문제가 있는 경우, 맞춘 확률이 높은 Class는 조금의 loss를, 맞춘 확률이 낮은 Class는 Loss를 훨씬 높게 부여한다.

    Optimizer

    : Loss 를 구하는 것 까지 진행했다면, 실제로 파라미터를 Update 하는 것

    각 모델 별로 W(Weight) 는 있지만, learning rate 와 방향(Weight의 변화율) 을 통해서 Update를 진행한다.

    Leraning Rate Scheduler

    : 학습시에 Learning rate를 동적으로 조절하기 위한 것

    • StepLR, CosineAnnealingLR, ReduceLROnPlateau
    #StepLR
    #특정 Step 마다 LR 감소
    scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=2, gamma=0.1)
    
    #CosineAnnealingLR
    #Cosine 함수 형태처럼 LR을 급격히 변경
    scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max = 10, eta_min=0)
    
    #ReduceLROnPlateau
    #더 이상 성능 향상이 없을 때 LR 감소
    scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min')

    StepLR
    CosineAnnealingLR
    ReduceLROnPlateau

    Metric

    : 학습에 직접적 영향(X), 단 모델이 학습이 잘 되었는가? 객관적으로 판단하게 되는 좋은 지표이다.

    → 애초에 데이터들의 Label 분포가 불균형, 너무 한 쪽으로 치우쳐져 있는 경우에 ACC 는 높은 것처럼 보이나 실제로는 정확도가 높지 않을 수 있다. 그래서 Balance 하게 데이터를 가꾸는 것도 성능에 중요한 요소이다.

    (중요!)

    Training Process

    : 실제로 PyTorch에서 동작되는 전체적인 Training 과정을 정리한다.

    model.train(mode = True)

    : 이는 module을 training mode로 Setting 해준다. 이를 왜 해주냐면, training/evaluation 과정에서 Dropout이나 BatchNorm 과정이 다르게 영향을 줄 수 있기 때문이다.

    for epoch in range(10): #전체 훈련을 몇번 돌 것인지?
        running_loss = 0.0
        for i, **data** in enumerate(trainloader, 0):
            #하나의 Batch 단위로 나올 수 있도록 for문을 더 잡는다.
            inputs, labels = data
            #data = [inputs, labels] 이다.
    
            optimizer.**zero_gard**()
            #zero_grad()의 의미!
            #얘를 먼저 하는 이유는, 매 Step 마다 이전 Step에 있는 Gradient가 남아 있기 때문에 초기화 해준다.
            #Grad를 초기화 할 것인가, 아닌가에 따라서 현재 Batch 마다 각각 적용할지 말지 결정하는 역할
    
            outputs = '나의모델'(inputs)
            loss = **criterion**(outputs, labels)
            loss.**backward**()
            # 각각의 parameter들의 Grad가 바뀌어 있을 것이다.
            # Grad 값을 변경한 것이 끝이 아니다. Update해주어야 한다.
            optimizer.**step**()
            # Update 해주는 함수! optimizer.
    
            running_loss += loss.item()
            if i % 2000 == 1999:
                print('[%d %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000))
                running_loss = 0.0

    Gradient Accumulation

    우리의 메모리는 한정되어 있다. 큰 배치 같은 경우에는 GPU 메모리가 감당하지 못 할 것이다. 그래서 Update하는 작용에서 Step을 건너 뛰어서 Gradient를 중첩시켜 놓고난 다음, Update를 진행시킨다. 이 방법이 Gradient Accumulation 이라고 한다.

    NUM_ACC = 2
    optimizer.zero_grad()
    for epoch in range(1000):
        running_loss = 0.0
        for i, data in enumerate(train_loader, 0):
            inputs, data= data
            outputs = '나의모델'(inputs)
    
            loss = criterion(outputs, labels) / NUM_ACC
            loss.backward()
    
            if i % NUM_ACC == 0:
                optimizer.step()
                optimizer.zero_gard()

    Inference Process

    model.eval()

    : 이는 evaluation mode로 세팅하는 함수이다.

    Inference는 파라미터를 Update하는 과정이 아니라, 우리가 만든 모델을 테스트하는 과정이다.

    with torch.no_grad(): #enter함수가 호출될 것이다.
        for data in testloader:
            images, labels = data
            outputs = '나의모델'(images)
            _, predicted = torch.max(outputs.data, 1)
            total += label.size(0)
            correct += (predicted == labels).sum().item()
    
    print("Acc" % (100 * correct/total))
    
    #with torch.no_gard() 함수 내부
    def __enter__(self):
        self.prev = torch.is_grad_enabled()
        torch.**set_grad_enabled**(False)
        #안에 있는 grad enabel을 False로 바꾼다.

    Appendix : PyTorch Lightning

    : 물론 학습의 입장에서는 이런 Process가 모두 이해하는 것이 중요하다. 하지만 현업에서는 생산성이 굉장히 중요하다. 그래서 PyTorch Lightning은 이런 모든 과정을 간략하게 보여주는 프레임(?) 느낌이다.

    반응형
Designed by Tistory.