본문 바로가기

Data Science/ML & DL

딥러닝 모델 개선 | 5. Learning rate(학습율) 조정

딥러닝 모델 개선 방법

  1. Epoch 수와 과적합
  2. DNN 모델 크기 변경
  3. Dropout Layer 추가를 통한 Overfitting 규제
  4. Batch Normalization (배치정규화)
  5. Optimizer의 Learning rate(학습율) 조정을 통한 성능 향상
  6. Hyper parameter tuning

Optimizer의 Learning rate(학습율) 조정을 통한 성능 향상

 
Optimizer의 Learning rate이 너무 크거나 너무 작으면 최적의 파라미터를 찾지 못할 수 있다.
그래서 Learning rate는 모델 성능과 밀접한 관계가 있는 아주 중요한 Hyper Parameter이다.
 

 학습률이란?
오차함수의 최적점의 기울기로 Gradient를 찾아가는데, 이때 최적점을 향해 움직이는 비율이 Learning rate이다.

 - 너무 높은 learning rate: 
                Gradient Exploding이 발생할 수 있다(step이 반복될수록 최적점에서 양 극단으로 점점 멀어짐)
 - 높은 learning rate:
                 최적점 근처까지는 도달하지만, 최적점의 근방에서 어느시점부터 개선이 안되는 경우가 생긴다.
 - 낮은 learning rate:
                 성능 개선이 너무 천천히 이뤄져서, epcoch가 끝나기 전에 충분한 성능 개선이 이뤄지지 않을 수 있음
- 학습이 오래 걸릴 경우 - 낮은 LR/학습 조금할 경우 - 높은 LR


학습률 조정은 ?
학습 하는 동안 고정된 하나의 Learning rate를 사용할 수도 있으나 학습이 반복되는 동안 학습률을 변경하여 성능을 향상시킬 수 있다.
    - 학습 도중 학습률을 어떻게 조정할 지 다양한 알고리즘들이 있다.
    - 보통초기 학습률은  0.01, 0.001을 사용한다
 
학습률 조정 알고리즘 lerning rate scedular정리 

 

 

 


예제

Learning rate decay

 
  • Optimizer와 Learning rate scheduler의 속성, 메소드 확인
    - 파이토치는 `torch.optim` 모듈에서 다양한 Learning rate 알고리즘을 제공

 

옵티마이저 설정 

- Adam을 많이 사용, 초기 파라미터 0.001로 설정

optimizer = torch.optim.Adam(bn_model.parameters(), lr=0.001)

 

 

옵티마이저 객체 관련 여러 정보조회 optimizer.param_groups

##  옵티마이저 객체관련 여러 정보들을 조회 => optimizer.param_groups
print(type(optimizer.param_groups), len(optimizer.param_groups))
print(type(optimizer.param_groups[0]))
info_dict = optimizer.param_groups[0]
info_dict.keys()

 

 

현재 learning rate 조희

info_dict['lr']  # 현재 learning rate

 

 

학습률 변화흐름 시각화

 

시각화 함수 만들기

### 학습률의 변화흐름을 시각화하는 함수
def plot_lr(title, lr_list):
    # title - 그래프 제목
    # lr_list - 에폭별로 적용된 Learning rate을 담은 리스트
    plt.figure(figsize=(10, 5))
    plt.plot(range(len(lr_list)), lr_list) 
    
    plt.title(title)
    plt.xticks([x for x in range(len(lr_list)) if x % 5 == 0], rotation=45)
    plt.xlabel("Epochs")
    plt.ylabel("LR")
    plt.grid(True, 
             axis="x", # x축 기준 그리드만 표시
             linestyle=":")
    plt.show()

 

시각화

# 테스트
plot_lr("My Scheduler", list(range(1, 1000, 10)))

 

학습률 스케줄러 1. Step LR

torch.optim.lr_scheduler.StepLR

optimizer = torch.optim.Adam(bn_model.parameters(), lr=0.001) 
# lr_scheduler : optimizer의 lr는 초기 학습률
step_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, # 학습률을 변화시킬 Optimizer
                                                 step_size=30, # 몇 step/epoch 마다 LR을 변경시킬지 간격
                                                 gamma=0.5, # 변경 비율. new_lr = 현재_lr * gamma
                                                )
# optimizer의 lr를 30 에폭/step 마다 0.5 배씩 변경
N_EPOCH = 200
STEP_SIZE = 10
steplr_list = []  # epoch별 lr 를 저장할 변수.

for epoch in range(N_EPOCH):
    
    # step
    for step in range(STEP_SIZE):  # for x, y in dataloader:
        # 학습
        # 모델 예측 -> Loss 계산 -> 파라미터 업데이트
        optimizer.step()
        # learning rate 변경 요청. => 30번 요청이 들어오면 변경 * gamma
        ## step단위로 변경.
        # step_scheduler.step()  
    step_scheduler.step()    # epoch 단위로 변경.
    steplr_list.append(step_scheduler.get_last_lr()[0])  # 현재 epoch의 lr를 저장.
plot_lr("Step LR", steplr_list)

학습률 스케줄러 2. CosineAnnealingLR

torch.optim.lr_scheduler.CosineAnnealingLR

 

- cosine 그래프를 그리면서 learning rate를 변경하는 방식

최근에는 learning rate를 단순히 감소시키기 보다는 감소와 증가를 반복하여 진동하는 방식으로 많이 사용(학습률 미세조정)

-  이러한 방법 중 가장 많이 사용되는 방법

# Annealing : 가열 <-> 냉각
optimizer = torch.optim.Adam(bn_model.parameters(), lr=0.001)
ca_scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, 
                                                          T_max=10, # 한 cycle 주기(단위: 에폭, step)
                                                          eta_min=0.00001, # 최소 학습률.
                                                         )
# 범위: 초기 LR  ~  eta_min
ca_lr_list = []
for epoch in range(N_EPOCH):
    # 한 에폭
    for step in range(STEP_SIZE):
        # 한 스텝
        optimizer.step()
    
    ca_scheduler.step()
    ca_lr_list.append(ca_scheduler.get_last_lr()[0])
plot_lr("CosineAnnealingLR", ca_lr_list)