들어가며
우리는 모델을 훈련시킬 때 fit() 함수를 사용하여 훈련시킨다
이 때 fit() 내부에서는 비용함수를 최소화하는 적절한 모델 파라미터를 찾는 작업이 이루어진다
적절한 파라미터를 찾는 방식에는 정규방정식이나 SVD, 경사하강법 등 여러가지가 있고
오늘은 그 중 경사하강법에 대하여 알아볼 것이다
그냥 fit() 함수 써서 훈련시키면 그만이지 굳이 내부적으로 어떻게 동작되는지 알아야하는가에 의문이 들 수 있다
하지만 어떻게 동작하는지 잘 알고있으면 적절한 모델, 작업에 맞는 좋은 파라미터를 빠르게 찾을 수 있다
경사하강법
경사하강법의 기본 아이디어는 비용 함수를 최소화하기 위해 반복해서 파라미터를 조정해가는 것이다

경사하강법의 원리는 파라미터 벡터인 θ에 대한 비용함수의 그레디언트(기울기)를 계산하고
그레디언트가 감소하는 방향으로 진행하며 그레디언트가 0이 되면 비용함수가 최솟값에 도달한 것이므로
목표에 맞는 적절한 파라미터를 찾아낸 것이다
구체적으로는 θ를 임의의 값으로 랜덤 초기화하여 시작해서
비용함수가 감소되는 방향으로 그레디언트를 수정해가며 비용함수가 최솟값에 수렴할 때까지 θ를 조정해나간다
그림을 보면 학습 스텝이라는 것이 있는데 이는 경사하강법에서 중요한 파라미터로 작용한다
학습률이라는 하이퍼파라미터로 결정되며 학습률이 커질수록 스텝의 크기가 커지고
학습률이 너무 작으면 반복을 많이 진행해야 해서 시간이 오래 걸린다
지역 최솟값 (local minimum)
모든 비용함수가 위의 사진처럼 매끈한 그릇 형태가 아니다
만약 함수가 볼록한 지점이 여러개이거나 특이한 지형의 형태를 띈다면
전역 최솟값보다 덜 좋은 지역 최솟값에 빠지게되는 문제가 발생할지도 모른다

만약 랜덤 초기화 값으로 결정된 파라미터 값이 왼쪽에서 시작된다면
지역 최솟값에서 최적의 파라미터라고 판단하여 전역 최솟값에 도달하지 못한다
반면 오른쪽에서 파라미터가 시작된다면 평탄한 지역에서는 기울기가 작아서
지나가는데에 시간이 오래 걸리고 평지에서 기울기가 0이된다면 일찍 멈추게 되어
전역 최솟값에 도달하지 못하는 문제가 발생한다
배치 경사 하강법
경사하강법은 배치 경사 하강법, 확률적 경사 하강법, 미니배치 경사 하강법 등으로 나뉠 수 있는데
우선 그 중 배치 경사 하강법에 대해 알아볼 것이다
배치 경사 하강법은 위에서 설명한 그대로인 가장 기본 형태의 경사하강법이다
경사 하강법을 구현하기 위해서는 파라미터에 대한 비용함수의 그레디언트를 계산해야한다
즉 파라미터가 바뀔 때 비용함수가 얼마나 바뀌는 지 그 변화율을 알아야 한다
이 때 비용함수의 변화율을 편도함수라고 부르며
편도함수는 비용함수를 파라미터에 대하여 편미분 한 것을 말한다

위 식에서 MSE()는 비용함수를 의미한다
어떤 모델의 파라미터가 여러개라면 각각에 파라미터에 대하여 편미분을 해야하여 번거롭고 실수하기가 쉽다
하지만 그레디언트 벡터를 사용하면 한꺼번에 계산할 수 있다
비용함수의 그레디언트 벡터는 파라미터마다의 편도함수들을 담고있는 벡터를 의미한다

경사 하강법의 스텝 즉 다음 파라미터를 계산하는 식은 아래와 같다

여기서 기호 η는 에타, 즉 학습률(스텝의 크기)를 의미한다
기존 파라미터에서 그 파라미터에 대한 비용함수의 변화율을 빼서 다음 파라미터를 구하는 방식이다
변화율을 빼주는 이유는 기울기가 감소하는 방향으로 나아가야하기 때문이다
경사하강법 알고리즘을 구현하면 아래와 같다
eta = 0.1 # 학습률
n_epochs = 1000
m = len(X_b) # 샘플 개수
np.random.seed(42)
theta = np.random.randn(2, 1) # 모델 파라미터를 랜덤하게 초기화합니다
for epoch in range(n_epochs):
gradients = 2 / m * X_b.T @ (X_b @ theta - y)
theta = theta - eta * gradients
전체 훈련 세트를 모두 사용해 한 번 학습하는 단위를 에포크(epoch)라고 한다
epoch와 학습률을 적절히 설정하여 모델이 빠르고 안정적이게 학습할 수 있도록 해야한다
확률적 경사 하강법
배치 경사 하강법은 매 스텝에서 전체 훈련세트를 사용하여 그레디언트를 계산하기에
훈련 세트가 커질경우 매우 느려진다는 단점이 있다
이를 해결할 방법으로는 확률적 경사 하강법을 사용하는 것이 있는데
확률적 경사 하강법은 매 스텝에서 한 개의 샘플을 랜덤으로 선택하고 그 하나의 샘플에 대한 그레디언트를 계산한다
하나의 샘플만 처리하면돼서 배치 경사하강법보다 훨씬 빠르고 큰 훈련 세트도 문제없이 훈련시킬 수 있다
하지만 하나의 샘플만 다루기때문에 전체 훈련세트를 다루는 배치 경사하강법보다 훨씬 불안정하다
매 스텝이 최솟값에 다다를 때 부드럽게 감소하는 것이 아닌 위아래로 요동치며 움직일 것이다

위 사진처럼 비용함수의 최솟값을 향해 파라미터가 불규칙하게 요동치면서 움직이는 것을 볼 수 있다
이런식으로 매우 불규칙할 경우 지역 최솟값을 건너뛰어 줄 수있다는 장점도 있지만
전역 최솟값에 다다르지 못할 수도 있다는 단점도 있게되는 딜레마가 생긴다
이 딜레마를 해결하기 위해서는 학습률을 점진적으로 감소시키는 방법이 있다
처음 시작할 때에는 학습률을 크게하여 지역 최솟값에 빠지지 않도록 하고
학습률을 점차 작게 줄여서 알고리즘이 전역 최솟값에 도달하도록 하는 것이다
이 때 매 반복에서 학습률을 결정하는 함수를 학습 스케쥴이라고 부른다
아래는 확률적 경사 하강법을 구현한 코드이다
n_epochs = 50
t0, t1 = 5, 50 # 학습 스케줄 하이퍼파라미터
def learning_schedule(t):
return t0 / (t + t1)
np.random.seed(42)
theta = np.random.randn(2, 1) # 랜덤 초기화
for epoch in range(n_epochs):
for iteration in range(m):
random_index = np.random.randint(m)
xi = X_b[random_index : random_index + 1]
yi = y[random_index : random_index + 1]
gradients = 2 * xi.T @ (xi @ theta - yi) # SGD의 경우 m으로 나누지 않습니다
eta = learning_schedule(epoch * m + iteration)
theta = theta - eta * gradients
확률적 경사 하강법에서 gradients를 구할 때 m으로 나누지 않는 이유는
훈련 과정에서 전체 훈련세트를 사용하지 않고
하나의 샘플만 사용해서 훈련하기 때문이다
learning_schedule의 파라미터의 값을 epoch*m+iteration으로 점점 커지게 설정하여
학습률 자체는 줄어들게 만드는 구조인 것을 확인할 수 있다
사이킷런에서 SGDRegressor 클래스를 통해 확률적 경사 하강법을 사용할 수 있도록 클래스를 제공한다
from sklearn.linear_model import SGDRegressor
sgd_reg = SGDRegressor(max_iter=1000, tol=1e-5, penalty=None, eta0=0.01,
n_iter_no_change=100, random_state=42)
sgd_reg.fit(X, y.ravel()) # fit()이 1D 타깃을 기대하기 때문에 y.ravel()로 씁니다
최대 1000번의 에포크(max_iter)동안 실행되거나
손실이 1e-5 보다 작아지는게 100 에포크 나타나게되면 학습을 종료한다
이는 불필요하게 오래 학습되는 것을 방지하기 위함이다
미니배치 경사 하강법
마지막으로 살펴볼 경사 하강법 알고리즘은 미니배치 경사 하강법이다
각 스텝에서 전체 훈련세트를 모두 사용하여 그레디언트를 계산하는 배치 경사하강법이나
하나의 샘플만 사용하여 그레디언트를 계산하는 확률적 경사 하강법과 달리
미니 배치 경사하강법은 미니배치라고 부르는 임의의 작은 샘플 세트에 대해서 그레디언트를 계산한다
이는 확률적 경사 하강법보다 덜 불규칙하게 움직이지만
지역 최솟값에서 빠져나오기는 더 힘들 수도 있다

위 사진은 세 가지 경사 하강법 알고리즘이 훈련 과정동안 파라미터 공간에서 움직인 경로를 나타낸다
배치 경사 하강법은 안정적으로 최솟값에 멈춘 것을 볼 수 있지만
확률적 경사 하강법과 미니 배치 경사 하강법은 최솟값 근처에서 요동치는 것을 볼 수 있다
배치 경사 하강법의 경우 안정적이지만 매 스텝에서 많은 시간이 소요되고
확률적 경사 하강법과 미니배치 경사 하강법의 경우
불안정하지만 적절한 학습 스케쥴을 설정한다면 최솟값에 잘 도달할 수 있으므로
상황을 적절히 고려하여 올바른 알고리즘을 선택하는 것이 중요하다
마치며
이번 글에서는 경사 하강법의 작동 원리와 경사 하강법의 여러 알고리즘에 대하여 알아보았다
경사하강법의 내용이 조금 많아서 쓰다보니 길어지게 된 것 같다
처음 원리만 보았을 때는 되게 쉬운 개념처럼 보였는데
막상 공부해보면 해볼수록 이해관계가 복잡해지고 개념들이 충돌하면서 굉장히 머리가 아팠다
하지만 그만큼 이해가 됐을 때 성취감이 되게 컸고 계속 공부할 맛이 난 것 같다
'AI > Machine Learning' 카테고리의 다른 글
| [AI] 릿지 회귀(ridge regression), 라쏘 회귀(lasso regression), 엘라스틱넷 회귀(elastic net regression) (1) | 2026.03.15 |
|---|---|
| [AI] 학습 곡선(Learning Curve) (0) | 2026.03.15 |
| [AI] 오차 행렬을 통한 오류 분석 (1) | 2026.03.02 |
| [AI] 다중 분류(multiclass classifier) (0) | 2026.03.02 |
| [AI] ROC곡선 (0) | 2026.03.01 |
