[딥러닝] 경사하강법
경사하강법(Gradient Descent)은 기계학습과 딥러닝에서 모델의 성능을 최적화하는 기본적인 알고리즘입니다. 복잡한 데이터셋에서 주어진 문제에 최적의 해답을 얻기 위해 반복적으로 접근하는 방법을 제공합니다. 목적은 모델의 손실 함수(loss function) 또는 비용 함수(cost function)를 최소화하는 파라미터(parameter) 값을 찾는 것입니다.
최적화 문제와 경사하강법의 정의
최적화 문제는 수학, 공학, 경제학 등 다양한 분야에서 발생합니다. 이 문제는 주어진 함수의 최소값 또는 최대값을 찾는 과정을 말합니다. 기계학습에서는 주로 손실 함수의 최소값을 찾는 최적화 문제를 다룹니다. 경사하강법은 이러한 최적화 문제를 해결하기 위해 함수의 기울기(gradient) 정보를 활용하여 함수의 최솟값을 찾아가는 반복적인 방법입니다. 기본적으로, 함수의 지역 최소값으로 점진적으로 이동함으로써 전역 최소값을 찾아가려고 시도합니다.
목적 함수와 손실 함수의 개념
- 목적 함수(Objective Function): 기계학습 모델의 목표를 수학적으로 정의한 함수입니다. 이 함수의 값을 최소화 또는 최대화함으로써 최적의 모델을 얻습니다. 분류, 회귀, 클러스터링 등 다양한 유형의 문제에서 모델 성능의 최적화를 위해 사용됩니다.
- 손실 함수(Loss Function): 모델의 예측값과 실제값 사이의 차이를 측정하는 함수입니다. 이 차이 또는 오차의 양을 최소화함으로써 모델의 성능을 최적화하려고 합니다. 손실 함수의 선택은 해결하려는 문제의 유형(예: 회귀, 분류)에 따라 달라질 수 있습니다.
Python 예시 (PyTorch를 사용한 경사하강법 구현)
이 예시에서는 PyTorch를 사용하여 간단한 선형 회귀 모델의 파라미터를 경사하강법을 통해 최적화하는 방법을 보여줍니다.
import torch
# 임의의 데이터셋
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32) # 입력 데이터
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32) # 출력 데이터
w = torch.tensor(0.0, dtype=torch.float32, requires_grad=True) # 초기 가중치
# 모델 예측 함수
def forward(x):
return w * x
# 손실 함수
def loss(y, y_predicted):
return ((y_predicted - y)**2).mean()
# 학습률
learning_rate = 0.01
# 반복 횟수
n_iters = 100
# 경사하강법 구현
for epoch in range(n_iters):
# 예측값 계산
y_pred = forward(X)
# 손실 계산
l = loss(Y, y_pred)
# 손실 함수의 기울기 계산
l.backward()
# 경사하강법을 사용한 가중치 업데이트 (torch.no_grad()로 기울기 추적 비활성화)
with torch.no_grad():
w -= learning_rate * w.grad
# 가중치 기울기 초기화
w.grad.zero_()
if epoch % 10 == 0:
print(f'Epoch {epoch+1}: w = {w:.3f}, loss = {l:.8f}')
이 코드는 선형 회귀 문제를 예시로 사용하고 있으며, 모델의 가중치(w
)를 경사하강법을 통해 업데이트함으로써 손실 함수의 값을 최소화하고 있습니다. 이와 같이 경사하강법은 모델 학습 시 핵심적으로 사용되는 최적화 알고리즘입니다.
경사하강법(Gradient Descent)은 최적화 방법 중 하나로 비용함수(Cost Function)를 최소화하기 위해 데이터 세트의 전체 또는 일부를 사용하여 가중치(Weights)를 업데이트하는 방법입니다. 경사하강법에는 주로 세 가지 유형이 있습니다: 배치 경사하강법(Batch Gradient Descent), 미니배치 경사하강법(Mini-batch Gradient Descent), 그리고 확률적 경사하강법(Stochastic Gradient Descent, SGD). 각각의 경사하강법에 대한 개념과 차이점을 살펴보겠습니다.
배치 경사하강법 (Batch Gradient Descent)
배치 경사하강법은 전체 데이터 세트를 사용하여 한 번에 가중치를 업데이트하는 방법입니다. 이 방법은 전체 데이터에 대해 가장 정확한 경사를 계산할 수 있으나, 데이터 세트가 매우 클 경우 계산 비용이 매우 높아질 수 있습니다.
예시 코드:
import torch
# 가정: X는 입력 데이터, y는 레이블, model은 이용할 모델, loss_fn은 손실 함수
def batch_gradient_descent(X, y, model, loss_fn, learning_rate):
# 가중치에 대한 기울기를 0으로 초기화
model.zero_grad()
# 예측
predictions = model(X)
# 손실 계산
loss = loss_fn(predictions, y)
# 역전파
loss.backward()
with torch.no_grad():
# 가중치 업데이트
for param in model.parameters():
param -= learning_rate * param.grad
미니배치 경사하강법 (Mini-batch Gradient Descent)
미니배치 경사하강법은 전체 데이터 세트를 더 작은 배치로 나누어 각 배치마다 가중치를 업데이트하는 방법입니다. 이 방법은 배치 경사하강법보다 계산 비용이 적고, SGD보다 안정적인 업데이트를 제공합니다.
예시 코드:
def mini_batch_gradient_descent(X, y, model, loss_fn, learning_rate, batch_size):
num_samples = X.shape[0]
indices = torch.randperm(num_samples)
for i in range(0, num_samples, batch_size):
batch_indices = indices[i:i+batch_size]
batch_x, batch_y = X[batch_indices], y[batch_indices]
# 가중치에 대한 기울기를 0으로 초기화
model.zero_grad()
# 예측 및 손실 계산
predictions = model(batch_x)
loss = loss_fn(predictions, batch_y)
# 역전파
loss.backward()
with torch.no_grad():
# 가중치 업데이트
for param in model.parameters():
param -= learning_rate * param.grad
확률적 경사하강법 (Stochastic Gradient Descent, SGD)
확률적 경사하강법은 각 업데이트에 단 하나의 데이터 샘플을 사용합니다. 이 방법은 매우 빠른 업데이트가 가능하나, 높은 변동성(variance)으로 인해 업데이트가 불안정할 수 있습니다.
예시 코드:
def stochastic_gradient_descent(X, y, model, loss_fn, learning_rate):
num_samples = X.shape[0]
indices = torch.randperm(num_samples)
for i in indices:
x_i, y_i = X[i:i+1], y[i:i+1]
# 가중치에 대한 기울기를 0으로 초기화
model.zero_grad()
# 예측 및 손실 계산
predictions = model(x_i)
loss = loss_fn(predictions, y_i)
# 역전파
loss.backward()
with torch.no_grad():
# 가중치 업데이트
for param in model.parameters():
param -= learning_rate * param.grad
각 경사하강법의 선택은 주로 데이터의 크기, 계산 비용의 제한, 그리고 얼마나 빠른 수렴을 원하는지에 따라 달라질 수 있습니다. 미니배치 경사하강법은 실제 많은 딥러닝 애플리케이션에서 가장 널리 사용되며 균형잡힌 접근법을 제공합니다.
경사하강법은 최적화 알고리즘으로, 함수의 기울기(경사)를 이용하여 함수의 최소값을 찾는 방법입니다. 이 과정은 비용 함수의 값을 최소화하거나 손실 함수의 값을 감소시키는 데 사용됩니다. 기계학습과 딥러닝에서, 경사하강법은 모델의 매개변수를 최적화하기 위해 널리 사용됩니다. 이 절에서는 경사하강법의 동작 원리를 세부적으로 설명하겠습니다.
기울기 계산
경사하강법의 첫 단계는 현재 위치에서 함수의 기울기(또는 그래디언트)를 계산하는 것입니다. 기울기는 함수의 가장 가파른 상승 방향을 나타내며, 기울기의 반대 방향으로 이동하면 함수의 최소값을 향해 나아갈 수 있습니다. 수학적으로, 기울기는 함수의 매개변수에 대한 편미분의 벡터로 표현됩니다.
예를 들어, 모델의 매개변수가 이고 손실 함수가 일 때, 기울기는 로 표현됩니다. 이는 에 대한 의 편미분을 의미합니다.
학습률(Learning Rate)의 역할
기울기를 계산한 다음, 학습률이라 불리는 하이퍼파라미터를 이용하여 매개변수를 얼마나 큰 단위로 업데이트할지 결정합니다. 학습률은 각 반복에서 매개변수를 얼마나 조정할지를 결정하는 스케일 요소로, 너무 작으면 최적값에 도달하는 데 오랜 시간이 걸리고, 너무 크면 최적값 주변을 지나쳐 발산할 수 있습니다. 적절한 학습률을 선택하는 것이 중요합니다.
반복적인 업데이트 과정
매개변수는 기울기의 반대 방향으로 학습률에 비례하는 크기로 조정됩니다. 즉, 매개변수 는 다음과 같은 공식에 따라 업데이트됩니다.
여기서 는 학습률을 나타냅니다. 이 과정을 반복함으로써, 손실 함수 의 값을 점차 감소시키며 최소값에 도달하게 됩니다.
PyTorch를 이용한 경사하강법 예시 코드
PyTorch를 사용할 때, 자동 미분(Autograd) 기능을 이용해 매개변수의 기울기를 쉽게 계산할 수 있습니다. 이를 이용한 간단한 예시는 다음과 같습니다.
import torch
# 손실 함수 정의 (예: y = (x - 5)**2)
def loss_fn(x):
return (x - 5)**2
# 시작점
x = torch.tensor([0.0], requires_grad=True)
# 학습률 설정
learning_rate = 0.01
# 경사하강법 반복 횟수
steps = 100
for step in range(steps):
# 손실 계산
loss = loss_fn(x)
# 기울기 계산
loss.backward()
# 기울기를 이용한 매개변수 업데이트 (기울기 추적 중지를 위해 torch.no_grad() 사용)
with torch.no_grad():
x -= learning_rate * x.grad
# 다음 반복을 위해 기울기를 0으로 초기화
x.grad.zero_()
print(f"Step {step+1}: x = {x.item()}, loss = {loss.item()}")
이 코드는 손실 함수 의 최소값을 찾기 위해 경사하강법을 사용합니다. 초기값 에서 시작하여, 반복마다 기울기를 계산하고 의 값을 업데이트하여 손실 함수의 최소값에 접근합니다.
경사하강법은 딥러닝 모델 훈련 중 파라미터를 최적화하기 위해 널리 사용되는 알고리즘입니다. 그러나 이 방법은 몇 가지 주요 문제에 직면할 수 있으며, 각각의 문제에 대해 효과적인 해결 방안이 존재합니다.
로컬 미니멈(Local Minimum)과 사들 포인트(Saddle Point)
문제점 설명:
로컬 미니멈은 비용 함수에서의 최소값이지만 전역 최소값(global minimum)은 아니며, 모델의 성능을 최적화하는 데 방해가 될 수 있습니다. 사들 포인트는 기울기가 0이지만 최소값이나 최대값이 아닌 점을 말하며, 이러한 점들 또한 경사하강법이 최적의 솔루션을 찾는 것을 어렵게 만듭니다.
해결 방법:
- 파라미터 초기화 전략을 신중하게 선택하여 시작점의 영향을 줄입니다.
- 모멘텀을 사용하여 로컬 미니멈을 벗어나도록 합니다.
학습률 조정 방법
문제점 설명:
일정한 학습률(learning rate) 사용은 훈련 초기에는 너무 느린 수렴을 초래하고, 후반에는 학습률이 너무 커서 최적점을 넘어서 발산할 수 있습니다.
해결 방법:
1. Adagrad
Adagrad는 각 매개변수에 대해 학습률을 동적으로 조절하여 학습률 문제를 해결합니다. 많이 변경된 파라미터는 작은 학습률을, 적게 변경된 파라미터는 큰 학습률을 가지게 됩니다.
Python 예시 (PyTorch):
import torch
optimizer = torch.optim.Adagrad(model.parameters(), lr=0.01)
2. RMSprop
RMSprop는 Adagrad의 단점을 보완하여, 과거 모든 그래디언트를 균등하게 고려하는 대신 최신 그래디언트들에 더 높은 가중치를 두어 조정합니다. 이를 통해 학습률이 너무 급격하게 감소하는 문제를 해결합니다.
Python 예시 (PyTorch):
optimizer = torch.optim.RMSprop(model.parameters(), lr=0.01, alpha=0.99)
3. Adam
Adam(Adaptive Moment Estimation)은 RMSprop와 유사하게 동작하지만, 모멘텀을 계산하여 그래디언트의 방향과 속도 모두를 고려합니다. 이로 인해 초기에는 빠른 방향 설정과 더 안정적인 수렴을 제공합니다.
Python 예시 (PyTorch):
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
이러한 학습률 조정 방법들을 통해서 경사하강법의 주요 문제점들을 해결하고, 딥러닝 모델의 훈련 과정을 더 효율적이고 안정적으로 만들 수 있습니다. 이러한 방법들의 선택은 특정 작업, 데이터셋의 특성과 모델 구조에 따라 달라질 수 있으며, 때로는 여러 방식을 결합하여 사용하기도 합니다.