딥러닝/이것저것

파이토치 자연어처리(16) - 최적화하기

SolartheNomad 2023. 3. 7. 22:11

** 머신러닝 파이프라인 구축하기 

*정적 학습률의 한계 

처음에 큰 학습률을 가져가되 현재 에포크의 손실값이 과거 에포크의 손실값에 비해 나아지지 않을 경우 

 

*학습률 스케쥴링 

- 문제마다 다른 최적의 학습률을 찾기 위한 튜닝 과정 

- 기본적으로 학습 초반은 학습률을 크게 가져가 숲을 보고, 학습 후반에 갈수록 미세한 가중치 파라미터 조정이 필요하다.

- 초기 학습률을 가지고 모델 최적화를 수행한다. 

- 일정 에포크 또는 이터레이션이 경과한 후에 감쇠를 시작하며 해당 에포크에서의 모델의 학습이 더 이상 진전되지 않을 떄 감쇠하기도 한다.

- 학습률 감쇠는 선형적으로 적용될 수 있으며 비율이 곱해지는

 

 

#적응형 학습률 : 기본 설정값을 사용하되 학습률을 상황에 따라 자동으로 정해질 수 있도록 하는 것

 

* 일반 최적화 수식

손실함수는 데이터셋의 샘플들에 대해 타깃 출력값과 

 

#적응형 학습률 알고리즘 종류 

 

1. 모멘텀 옵티마이저

- 시작부터 매번 계산된 그레디언트를 누적하는 형태로 구현됨

- 지역 최소점을 쉽게 탈출하기가 가능

- 학습 속도를 가속화한다. 

 

 

2. 아다그래드 옵티마이저 

- 가중치 파라미터마다 별도의 학습률을 가진다.

 

 

아담 옵티마이저 적용하기

파이토치 자연어처리(15)의 캘리포니아 주택 데이터셋의 SGD를 아담으로 교체해보자

 

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import fetch_california_housing 


california = fetch_california_housing()
df = pd.DataFrame(california.data, columns = california.feature_names)
df["Target"] = califronia.target
df.tail()


#표준 스케일링을 적용하여 입력데이터를 정규화 & 전처리 해준다. 
scaler = StandardScaler()
scaler.fit(df.values[:, :-1])
df.values[:, :-1] = scaler.transform(df.values[:, :-1])
df.tail()

# 파이토치 패키지 불러오기(학습 시작)
import torch 
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

#x,y 설정해주고 파이토치 텐서로 변경해주기 

data = torch.from_numpy(df.values).float()
x = data[:,:-1]
y = data[:,-1:]

print(x.shape, y.shape)

#설정값 세팅

n_epoch = 4000
batch_size = 256
print_interval = 200
#learning_rate =le-2 : 아담 옵티마이저에서는 학습률이 필요 없음 (다만 트랜스포머를 쓰게 될 때는 필요하다.)

#심층신경망 만들기

model = nn.Sequential(
    nn.Linear(x.size(-1),6),
    nn.LeakyReLU(),
    nn.Linear(6,5),
    nn.LeakyReLU(),
    nn.Linear(5,4),
    nn.LeakyReLU(),
    nn.Linear(4,3),
    nn.LeakyReLU(),
    nn.Linear(3, y.size(-1)),
    
)

# 만든 모델을 옵티마이저에 등록시키기 : 파이토치 자연어처리(15)에서는 optim.SGD 클래스를 통해서 optimizer을 생성하였지만 이번에는 lptim.Adam을 통하여 옵티마이저 생성하기
# Adam.optimzer은 transformer을 제외하고 learning-rate가 필요하지 않다.

optimizer = optim.Adam(model.parameters()) #optimizer 생성과 동시에 model을 optimizer에 등록시키기

#학습 진행하기

# |x| = (total_size, input_dim)
# |y| = (total_size, output_dim)

for i in range(n_epochs):
    #index를 섞기 
    indices = torch.randperm(x.size(0)) #섞은 index를 indices 변수에 저장하기
    x_ = torch.index_select(x, dim=0, index=indices) #x 변수 안에 indices 넣기
    y_ = torch.index_select(y, dim=0, index=indices) #y 변수 안에 indices 넣기 
    
    x_ = x._split(batch_size, dim=0)
    y_ = y._split(batch_size, dim=0)
    
   # |x_[i]| = (batch_size, input_dim)
   # |y_[i]| = (batch_size, output_dim)
   
   y_hat = []
   total_loss = 0
   
   for x_i, y_i in zip(x_, y_):
      #|x_i| = |x_|