네이버 부스트캠프 AI Tech 2기

[08.26 P Stage Day4] - 📝 Training & Inference

Jay x 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은 이런 모든 과정을 간략하게 보여주는 프레임(?) 느낌이다.

반응형