[WEEK01-DAY3] 경사하강법

2024. 8. 14. 00:09Machine Learning/[TIL] Naver Boost Camp

경사하강법

경사하강법은 기계학습모델 및 신경망을 훈련하는데 일반적으로 사용되는 최적화 알고리즘이다. [IBM] gradient-descent

 

경사하강법은 신경망이 스스로를 개선하는 방법 중에 하나이다. 신경망은 예측을 하고, 예측이 얼마나 틀렸는지 알려주는 손실함수를 사용한다. 이때, 이 손실을 줄일 수 있는 방법으로 경사하강법을 사용한다. 경사하강법은 손실함수의 기울기를 계산하고, 이 기울기를 따라 조금씩 나아가며 손실을 줄인다. 이런 방법을 반복하면 신경망은 예측을 개선하고 모델을 최적화하게 된다. [wikidocs] 경사하강법

 

출발점은 우리가 성능을 평가하기 위한 임의의 지점일 뿐이다. 그 시작점에서 우리는 도함수(또는 기울기)를 찾고 거기에서 접선을 사용하여 기울기의 가파른 정도를 관찰할 수 있다. 기울기는 매개변수, 즉 가중치와 편향에 대한 업데이트를 알려준다. 시작점의 기울기는 더 가파르지만 새로운 매개변수가 생성됨에 따라 수렴점으로 알려진 곡선의 가장 낮은 지점에 도달할 때까지 기울기가 점차 감소해야한다. [IBM] gradient-descent

 

경사(기울기)에 대한 수식 표현은 아래와 같다.

$$ \frac{\partial l(w, b)}{\partial w} = \frac{\partial l(w, b)}{\partial y} \frac{\partial y}{\partial w} =\frac{l(w, b)의 증가량}{w의 증가량} $$

 

경사(기울기)에 대한 코드 표현은 아래와 같다.

현재 손실 값에 대한 경사(기울기)를 자동 미분을 사용하여 계산한다.

loss.backward()

학습률

머신러닝과 신경망 훈련에서 매우 중요한 하이퍼파라미터로, 최소 단계에 도달하기 위해 취하려는 단계의 크기(가중치가 업데이트되는 크기)이다. 학습률이 높으면 더 큰 단계가 발생하지만 최소 단계를 초과할 위험이 있고 반대로 학습률이 낮으면 단계 크기가 작아진다. 정밀도가 더 높다는 장점이 있지만 반복 횟수는 최소값에 도달하는데 더 많은 시간과 계산이 필요하기 때문에 전반적인 효울성을 떨어뜨린다. [IBM] gradient-descent

학습률은 모델과 데이터에 따라 달라지므로, 실험과 검증을 통해 최적의 값을 찾는 것이 중요하다.

 

가중치 w값 업데이트의 수식 표현은 아래와 같다.

$$ w^* = w - \alpha \frac{\partial l(w, b)}{\partial w}  $$

 

계산된 기울기(경사)를 사용하여 가중치 w값을 업데이트하는 코드 표현은 아래와 같다.

optimizer.step()

 

경사하강법의 작동 원리

import torch
import torch.nn as nn
import torch.optim as optim

# 간단한 모델 정의
model = nn.Linear(1, 1)
optimizer = optim.SGD(model.parameters(), lr=0.01)

loss_function = nn.MSELoss()

for epoch in range(num_epochs):
    y = model(x_tensor)    
    loss = loss_function(y, t_tensor)    
     
    optimizer.zero_grad() 
    loss.backward()
    optimizer.step() 
    
    print(f'Epoch {epoch+1}, Loss: {loss.item()}')

 

1. optimizer.zero_grad()

누적된 기울기를 방지하기 위해 매번 기울기를 0으로 초기화하는 설정하는 과정이다.

 

PyTorch에서는 gradients 값들을 추후에 backward를 해줄 때 계속 더해주기 때문에 항상 backpropagation을 하기 전에 gradients를 zero로 만들어주고 시작해야한다. 참고한 블로그

 

2. loss.backward()

Require_grad=True로 설정된 모든 텐서들에 대해 gradient를 계산한다. gradient 계산이 시작되는 지점인 loss 변수에 아래와 같이 적용해주어야한다.

loss.backward()

backward() 메소드는 gradient를 구하려고 하는 변수들(Required_grad=True로 전달한 변수들)에 대해 Dynamic Computational Graph에 neural net의 계산 흐름을 쌓게 된다.

 

Dynamic Computational Graph (LinearRegressionModel의 연산 및 역전파 과정 시각화)

torchviz.make_dot(y, params=dict(model.named_parameters()))

 

.grad를 통해 gradient의 실제 값을 확인할 수 있다. 여기서 중요한 내용은 바로 gradient들이 축적된다는 것이다. 모델이 실행될 때마다 원래 값에 새로운 값이 계속 더해진다는 의미로optimizer.zero_grad()을 하는 이유가 바로 축적때문이다. [velog] autograd

 

3. optimizer.step()

optimizer 객체는 저장된 기울기(.grad)를 사용하여 각 파라미터를 업데이트한다.

for param in model.parameters():
    param.data -= learning_rate * param.grad.data

확률적 경사하강법

각각의 데이터 포인트마다 오차를 계산하여 가중치 w와 바이어스 b를 업데이트하는 최적화 알고리즘.

확률적 경사하강법 코드 표현은 아래와 같다.

optimizer = optim.SGD(model.parameters(), lr=0.01)

에폭

각 에폭마다 모델의 가중치 w값이 업데이트되므로, 여러 번의 에폭을 통해 모델의 성능이 향상될 수 있지만, 에폭 수가 너무 많으면 과적합이 발생할 수 있다.

데이터 표준화

손실 값을 줄이기 위해 모델을 구축하기 전에 데이터를 전처리하는 방법.

from sklearn.preprocessing import StandardScaler
scaler_x = StandardScaler()
x_scaled = scaler_x.fit_transform(x.reshape(-1, 1))
from sklearn.preprocessing import StandardScaler
scaler_x = StandardScaler()
x_scaled = scaler_x.fit_transform(x.reshape(-1, 1))