강의자료/머신러닝

머신러닝] 경사하강법

파아란 기쁨 2023. 11. 16. 09:08

데이터를 처리하는 방법 이해하기

슈퍼마켓에서 다음과 같이 온도에 따른 아이스크림 판매량을 조사한 테이블이 있다.

온도 판매량
5 7
9 9
11 14
14 16
17 17

이 때 한 여름에 30도가 되었을 때 이 슈퍼마켓의 아이스크림 판매량이 어느 정도가 될지 궁금하다.

우리는 위와 같이 어떤 값을 예측을 하기 위해 y=ax+b 와 같은 형태의 식을 이용하여 a와 b를 찾고 거기에 x의 값에 30을 넣어서 y의 값을 찾는다. 이것이 선형회귀이다.

이 때 어떤 a와 b의 값을 찾았을 때 위와 같이 오차가 발생하는데 예측하는 값과 실제값 사이의 평균적인 오차를 가장 적게 만드는 a와 b를 찾아야 한다.

결국 위의 그림에서 빨간 선분들의 길이의 합이 최소가 되는 직선의 기울기 a를 찾으면 된다는 것을 알 수 있다.

일차함수 f(x)=ax 에서 자료의 좌표를 차례로(xi,yi)라 하면 오차의 평균은 다음과 같이 나타낼 수 있다.

$$ \frac{1}{5}\sum_{i=1}^5|y_i-f(x_i)| $$

일반적으로 미분을 쉽게 하도록 하기 위해 절댓값 대신 오차를 제곱하고 1/2을 곱한 식인 다음과 같이 평균 오차를 계산한다.

$$ \frac{1}{2}\frac{1}{5}\sum_{i=1}^5(y_i-f(x_i))^2 $$

위와 같이 모델의 예측값과 실제값 사이의 오차를 나타내는 함수를 손실함수라고 한다.

이것을 일반화 하여 정리하면 다음과 같은 식으로 만들 수 있다.

$$ E(손실함수)=\frac{1}{2}\frac{1}{m}\sum_{i=1}^m(y_i-f(x_i))^2 $$

이러한 손실 함수의 최솟값은 어떻게 찾을 수 있을까?

위의 데이터를 기준으로 손실함수 E(a)는 다음과 같이 계산 할 수 있다.

$$ E(a)=\frac{1}{2}\frac{1}{5}\sum_{i=1}^5(y_i-f(x_i))^2 $$

$$ =\frac{1}{10}((5a-7)^2+(9a-9)^2+(11a-14)^2+(14a-16)^2+(17a-17)^2) $$

$$ =\frac{1}{10}(712a^2-1566a+871)  $$

 즉 손실 함수는 a에 대한 이차 함수로 표현되며  그래프로 그려 보면 다음과 같다.

 

 

경사하강법이란

위의 그래프에서 손실함수 E(a)의 값이 최소일 때 근접한 예상 값을 찾을 수 있다는 사실은 자명하다.

그렇다면 이러한 모델을 어떤 방법으로 찾을 것인가의 문제가 발생한다.

경사하강법의 기본 아이디어는 비용함수를 최소화 하기 위해 반복해서 파라미터를 조정해 가는 것이다.

흔히 산에 등산을 갔던 등산객이 갑자기 밤이 되어 앞이 보이지 않는 상황과 비유를 많이 한다.

산에 올라간 등산객이 무사히 아래로 내려 올 수 있는 방법을 생각해 보면 발을 조금씩 디디면서 높은 곳이 아닌 낮은 곳으로 또한 기울기가 가장 가파른 방향으로 발걸음을 내딛다 보면 산 아래로 내려 올 수 있는 상황이 바로 경사 하강법의 원리이다.

파라미터 벡터 θ 에 대해 비용 함수의 현재 그레이디언트gradient를 계산한다. 그리고 그레이디언트가 감소하는 방향으로 진행한 다음 그레이디언트가 0이 되면 최솟값에 도달한것이다.

출처 : https://tanay-blogs.medium.com/the-gradient-descent-algorithm-f0c14efff5ad

여기서 모델 파라미터는 랜덤하게 초기화된 후 반복적으로 수정되어 비용함수를 최소화 한다. 학습 스텝 크기는 비용 함수의 기울기에 비례한다. 따라서 비용이 최솟값에 가까워질수록 스텝 크기가 점진적으로 줄어든다.

하지만 모든 비용함수가 매끈한 그릇 같지는 않다.

출처 : https://www.mltut.com/stochastic-gradient-descent-a-super-easy-complete-guide/

위와 같은 경사하강법에서 랜덤 초기화 부분으로 전역 최솟값 보다 덜 좋은 지역최솟값에 수렴하게 된다.

다행히 선형회귀를 위한 MSE 비용함수는 곡선에서 어떤 두 점을 선택해 선을 그어도 곡선을 가로 지르지 않는 볼록 함수이다. 따라서 경사 하강법이 전역 최솟값에 가깝게 접근 할 수 있다는 것을 보장한다.

 

경사하강법의 이해를 돕기 위한 사이트 - https://angeloyeo.github.io/2020/08/16/gradient_descent.html

 

경사하강법(gradient descent) - 공돌이의 수학정리노트 (Angelo's Math Notes)

 

angeloyeo.github.io

 

배치 경사 하강법

배치경사하강법(Batch Gradient Decent)는 전체 데이터 셋에 대한 에러를 구한 뒤 기울기를 한번만 계산하여 모델의 파라미터를 업데이트 하는 방법을 말한다. 여기서 한번의 의미는 배치 단위가 아닌 전체 데이터셋이다.

배치 경사 하강법의 장점은 전체 학습데이터에 대해 한번의 업데이트가 이루어지므로 연산횟수가 적고 전체 데이터에 대한 그래디언트를 계산하기 때문에 최적으로의 수렴이 안정적으로 진행 된다.

단점으로는 한 스텝의 모든 학습데이터를 사용하기 때문에 학습시간이 오래 걸리고 지역 최적화 상태가 되면 빠져 나오기 힘들고 많은 메모리가 필요하다.

 

이러한 배치 경사 하강법을 구현하려면 각 모델 파라미터 θj 대해 비용 함수의 그레이디언트를 계산해야 한다. 이를 편도함수라고 한다.

즉 3차원 세상 이상이라면 동쪽에서 바라본 산의 기울기, 서쪽에서 바라본 산의 기울기... 와 같이 모든 차원에서 바라보는 기울기를 찾아 준다는 의미이다.

θj 에 대한 비용함수의 편도함수는 다음과 같다.

$$ \frac{\partial}{\partial \theta_j}MSE(\theta)=\frac{2}{m}\sum_{i=1}^m(\theta^Tx^{(i)}-y^{(i)})x_j^{(i)} $$

비용함수 MSE( θ )를 θj 에 관해 편미분한 것이다.

모델 파라미터 θ 가 많아질 경우 다음과 같이 벡터화를 통해 일괄 계산할 수 있다.

$$ \triangledown_\theta MSE(\theta) = \left(\begin{array}{c}\frac{\partial }{\partial \theta_0}MSE(\theta)\\ \frac{\partial }{\partial \theta_1}MSE(\theta)\\...\\\frac{\partial }{\partial \theta_n}MSE(\theta)\end{array}\right) = \frac{2}{m}X^T(X\theta - y) $$

이는 각 모델 파라미터 θ 마다의 편도 함수를 모두 담고 있다. 

위의 식에서 X는 샘플수(m*n) 행렬이며 n개의 파라미터를 가진 n*1 벡터 θ 와 곱해서 m*1 벡터를 만든다. 같은 크기의 y벡터를 빼고 X 자기자신과 곱셈을 위해 X행렬을 전치시켜 n*m 행렬로 바꿔 곱하면 최종 계산 결과는 파라미터 수와 같은 n*1 벡터가 된다.

이렇게 그레디언트 벡터가 구해지면 다음 스텝으로 가기 위한 θ 를 구해야 하는데 여기서 학습률 η (에타)가 사용된다.

내려가는 스텝의 크기를 결정하기 위해 그레이디언트 벡터에 η (step size / learning rate 라고도 함)를 곱한다.

$$ \theta^{(next step)} = \theta - \eta \triangledown_ \theta MSE(\theta) $$

 

출처 : https://everyday-deeplearning.tistory.com/entry/SGD-Stochastic-Gradient-Descent-%ED%99%95%EB%A5%A0%EC%A0%81-%EA%B2%BD%EC%82%AC%ED%95%98%EA%B0%95%EB%B2%95

  

위에서 θ 에서 학습률을 곱한 그레디언트 벡터를 빼는 이유는 스텝이 좌측에서 시작한 경우 기울기는 음(-)의 값을 가지므로 - 와 만나 θ 값을 키워 우측으로 이동하고 우측에서 시작한 경우는 기울기는 양(+)의 값을 가지므로 - 와 만나 θ 값을 줄여 좌측으로 이동해야 하기 때문이다.

이 것을 파이썬으로 구현해 보면 다음과 같다.

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)
X = 2*np.random.rand(100,1)
y = 4 + 3 * X + np.random.randn(100,1)
X_b = np.c_[np.ones((100,1)), X]    # 절편항을 위해 1열에 1값 추가

lr = 0.1   # 학습률 설정
n_iter = 1000           # 반복 횟수 설정
m = len(X_b)              # 샘플 수

theta = np.random.randn(2,1)  # 무작위 초기값 설정

for iter in range(n_iter):
    gradients = 2/m * X_b.T@(X_b@(theta) - y)  # 배치 경사하강법
    theta = theta - lr*gradients          # next step

theta 값을 출력해 보면 다음과 같다.

array([[4.21509616],
       [2.77011339]])

이전에 정규방정식으로 찾은것과 일치한다.

 

 

출처) 핸즈온 머신러닝

http://matrix.skku.ac.kr/KOFAC/book/

 

인공지능 수학 과목 시안 v3

 

matrix.skku.ac.kr

 

사업자 정보 표시
원당컴퓨터학원 | 기희경 | 인천 서구 당하동 1028-2 장원프라자 502호 | 사업자 등록번호 : 301-96-83080 | TEL : 032-565-5497 | Mail : icon001@naver.com | 통신판매신고번호 : 호 | 사이버몰의 이용약관 바로가기