home search
Math
Machine Learning
Mathematics for Machine Learning 7.1장: 최적화 - 경사하강법을 이용한 최적화
2023. 01. 29

이 내용은 책 Mathematics for machine learning(Marc Peter Deisenroth et al.)을 기반으로 하고 있습니다.

7장 서문

최적화

머신러닝 모델을 학습시키는 것은 좋은 파라미터를 찾는 문제가 되기도 한다. 좋은 파라미터란, 목적 함수(objective func.)이나 확률적 모델(probabilistic model)로 결정할 수 있다. 목적함수가 주어졌을 때 가장 좋은 값은 최적화 알고리즘(optimization algorithm)으로 찾을 수 있다.

7장에서는 연속적 최적화(continous optimization)을 볼 것이며, 이는 다시 unconstrained와 constrained 최적화로 나뉜다. 이번 장에서는 나오는 함수는 미분 가능하며 그를 통해 최적값을 도출할 수 있다고 가정한다.

Minimum

보통 머신러닝에서 목적함수(보통 손실 함수이며, 예측값과 실제 정답 간의 차이이다. 따라서 작을 수록 좋다)는 최소화될 수 있게 설계되고, 최적값은 최솟값이다. 고등학교 수학 과정을 떠올려보면, 어떤 함수의 그래프에서 가장 낮은 값 혹은 가장 높은 값은 그 함수를 미분했을 때 0이 되는 지점에서였다. 우리는 그걸 극소값 혹은 극대값이라 불렀다. 마찬가지다.

목적함수의 가장 낮은 곳(valley)에서 최적값을 찾을 수 있으며, 그래디언트는 언덕을 오르는 방향이다. 따라서, 최적화의 기본적 아이디어는, 그래디언트의 반대 방향, 즉 언덕을 내려가는 방향으로 움직여가며 가장 깊은 지점을 찾아가는 것이다.

image

위 그림은 목적 함수 $l(x) = x^4 + 7x^3 + 5x^2 -17x + 3$를 나타낸 것이다. 이 함수가 가장 작은 값을 가지는 지점은 약 $x=-4.5$ 지점이다. 이를 Global minimum(최솟값)이라고 한다. 반면 약 $x=0.7$ 부근에서는 함수가 값이 낮아지긴 하지만 함수 전체로 최소는 아니다. 국소적으로 봤을 때만 최소라 하여 local minimum이라 한다.

그래디언트가 0인 지점을 stationary points(정지점)이라고 하는데, 다시 말해 미분한 함수가 0인 점이다. (여전히 고등과정과 같은 말이다) 따라서 그래디언트를 $\cfrac{\mathrm{d}l(x)}{\mathrm{d}x} = 4x^3 + 21x^2 + 10x - 17$ 로 구했다 하면, 이것이 0인 지점에서 local 혹은 global minimum일 확률이 높다.

물론 극소점만 있는 것은 아니다. 그래프에서 약 $x=-1.5$ 지점처럼 극대점도 있다. 그럼 그 점이 극소인지 극대인지는 어떻게 알까? 미분을 다시 하면 된다. 이차 미분값이 음수이면 ($\cfrac{\mathrm{d}^2 l(x)}{\mathrm{d}x^2} < 0$) maximum을 양수이면 minimum을 갖는다.

앞서 minimum을 찾기 위해 음의 그래디언트는 방향으로 움직여야 한다고 했다. (얼마만큼 움직일지 그 보폭을 ‘step size’ 혹은 ‘learning rate’라 한다) 위 그래프에서 왼쪽에서 시작해 기울기가 음수인 방향으로 조금씩 움직였다고 하면 대번에 global minimum에 도달한다. 하지만 반대로 오른쪽에서 시작했다면 local minimum에 빠지게 되고, 그곳이 최적값이라 오인할 수도 있다. (그래프가 아주 복잡해서 어디가 global minimum인지 모를 경우 특히)

Convec func.

7.3절에서는 convex function이라 부르는 함수가 나올텐데, 이 함수는 어디서 시작했는지와는 상관 없이 모든 local minimun이 global minimum이다. 따라서 많은 머신러닝 목적 함수들이 convex 형태로 만들어지기도 한다.


7.1. Optimization Using Gradient Descent

본격적으로 경사하강법을 이용한 최적화를 알아보자.

대체로 우리의 목적함수 $f: \mathbb{R}^d \rightarrow \mathbb{R}$ 를 최소화하는 ($\min\limits_x f(\boldsymbol{x})$) 문제를 풀고자 한다.

경사하강법(gradient descent)은 1차(first-order) 최적화 알고리즘이다. 경사하강법을 이용해 함수의 local minimum을 찾기 위해선, 현 시점에서 함수의 음의 그래디언트 방향으로 움직여야 한다. 그래디언트는 가장 가파른 상승 방향을 나타내기 때문에, 그 음의 방향으로 움직이면 가장 빠르게 감수할 수 있다.

함수를 다변수 함수 $f(\boldsymbol{x})$로 확장해 보자면, 그래디언트는

\[-((\triangledown f)(\boldsymbol{x}_0))^T\]

이고, 아래와 같은 움직임을 갖는다. 작은 보폭(step-size, learning rate, 경사를 따라 움직이는 정도) $\gamma \ge 0$에 대해

\[\boldsymbol{x}_1 = \boldsymbol{x}_0 - \gamma ((\triangledown f)(\boldsymbol{x}_0))^T\]

음의 그래디언트 방향으로 움직였으므로 $f(\boldsymbol{x}_1) \le f(\boldsymbol{x}_0)$ 관계가 성립한다.

이 원리를 반복적으로 진행시키면 그것이 경사하강법 알고리즘이다. 우리가 함수 $f: \mathbb{R}^d \rightarrow \mathbb{R}, \boldsymbol{x} \mapsto f(\boldsymbol{x})$ 의 극솟값(local minimum) $f(\boldsymbol{x}_*)$ 을 찾을 때, 파라미터의 초기값 $\boldsymbol{x}_0$ 에서 시작해 아래와 같은 식을 반복한다.

\[\boldsymbol{x}_{i+1} = \boldsymbol{x}_i - \gamma_i ((\triangledown f)(\boldsymbol{x}_i))^T\]

적당히 알맞은 step-size $\gamma_i$ 에 대해 $f(\boldsymbol{x}_0) \ge f(\boldsymbol{x}_1) \ge \cdots$ 는 local minimum으로 수렴한다.

아래 그림을 보면 좌하단 어느 지점에서 시작해 점점 가장 낮은 곳으로 이동해가는 것을 알 수 있다.

image

하지만 minimum으로 갈수록 경사하강법은 느리게(조금씩) 움직인다. 또한 minimum 점으로 향하는 거의 수직 방향으로 지그재그 형태로 움직이기도 한다.


7.1.1 Step-size

Step-size는 말 그대로 보폭, 얼마씩 움직이는가를 말한다. learning rate(학습률)이라고도 많이 한다. 그래서 파이토치 등 프레임워크에서 ‘lr’이라고 하면 학습률을 일컫는다.

step-size가 너무 작으면 경사하강은 매우 느리게 일어난다. 아무리 가파른 경사라도 조금씩만 움직이기 때문이니 당연한 얘기다. 반대로 step-size가 너무 크면 경사하강법은 overshoot하거나 수렴에 실패하거나, 발산하기까지 한다.

그래디언트를 적응적으로(adaptive, 그때그때 알맞게 바꿔가며) 적용하는 방식은 함수의 국소적(local) 성질에 따라 step-size를 각 반복(iteration)마다 재조정해간다. 대표적으로,

  • gradient step한 뒤 함숫값이 증가하면 step-size가 너무 큰 것이다. 그땐 그 step을 물리고(다시 뒤로) step-size를 줄인다
  • 반대로 함숫값이 감소한다면, step-size를 키워볼 만하다.

선형연립방정식 $\boldsymbol{Ax} = \boldsymbol{b}$의 해를 구한다 생각해보자. 경사하강법의 수렴 속도는 condition number(조건수)에 따라 결정된다.

condition number

행렬 $\boldsymbol{A}$의 최대 특이값(singular value)과 최소 특이값의 비율이다. $$ \kappa = \cfrac{\sigma(\boldsymbol{A})_{\max}}{\sigma(\boldsymbol{A})_{\min}} $$

Condition number은 가장 굴곡이 큰 방향과 가장 적은 방향의 비율이라 볼 수도 있다. (좁고 긴 valley 형태에서 나쁜 값을 보인다.)

$\boldsymbol{Ax} = \boldsymbol{b}$을 푸는 것보단 $\boldsymbol{P}^{-1}(\boldsymbol{Ax} - \boldsymbol{b}) = \boldsymbol{0}$ 을 풀 수도 있는데, 이때 $\boldsymbol{P}$을 preconditioner (전제조건)이라고 한다. $\boldsymbol{P}^{-1}\boldsymbol{A}$이 더 나은 condition number을 갖으며, 동시에 계산하기 쉬운 $\boldsymbol{P}^{-1}$ 을 찾는다.


7.1.2. Gradient Descent with Momentum

앞서 보았듯이, 기본적 경사하강법은 느린 수렴을 보일 수도 있으며, 그 계산 과정에서 메모리 소모가 심할 우려가 있다. 이를 해소하기 위한 여러 방법들이 논의되어왔고, 이번 장에서는 모멘텀을 이용한 경사하강법을 말하고자 한다.

물리를 배운 사람이라면 모멘텀(momentum)이란 용어가 낯설지 않을 것이다. 물리에서 ‘운동량’이라고도 부르는 모멘텀은 질량과 속도 벡터의 곱으로 나타내는 물리량이다. (위키백과 참조) 일례로, 빠르게 움직이는 무거운 물체는 운동량이 크다.

경사하강법에서 말하는 모멘텀도 같은 성질을 이용한다. 경사를 따라 굴러가는 공을 떠올려보자. 무거운 공일수록 자신이 움직이고 있던 방향으로 계속 움직이려 하지, 급격하게 방향을 바꾸지 않는다.

Gradient Desecnt with momentum은 직전 반복(iteration)에서 무엇이 일어났는지 기억할 수 있는 모멘텀 항을 더한다. 이 메모리 항(기억한단 의미에서 ‘memory’라고 칭한 것.)은 움직임을 살짝 둔화시키고 경사 업데이트를 보다 부드럽게 만든다.

쉽게 말해, 이전 움직임을 현재 움직임에 반영한다. 마찬가지로, 이전 움직임이 매우 가파른 경사를 통해서였다면, 이번 경사가 아무리 이전과 다르다 해도 이전 방향과 크기를 어느정도 반영한단 뜻이다.

이를 식으로 표현해보면

\[\begin{aligned} &\boldsymbol{x}_{i+1} = \boldsymbol{x}_{i} - \gamma_i((\triangledown f)(\boldsymbol{x}_{i}))^T + \alpha \triangle \boldsymbol{x}_{i} \\ &\triangle \boldsymbol{x}_{i} = \boldsymbol{x}_{i} - \boldsymbol{x}_{i-1} = \alpha \triangle \boldsymbol{x}_{i-1} - \gamma_{i-1}((\triangledown f)(\boldsymbol{x}_{i-1}))^T \\ & (\alpha \in [0, 1]) \end{aligned}\]

모멘텀 항을 도입함으로써 평균과 같은 효과를 내며 그래디언트의 노이즈를 상쇄시킬 수 있다.


7.1.3. Stochastic Gradient Descent

머신러닝에서의 적용 방식을 더 자세히 살펴보겠다. 데이터 n($1, \cdots , N$)개가 있을 때, 각 n에 대한 손실 $L_n$의 합으로 목적함수를 나타낸다. 학습을 진행하며 L을 최소화하는 파라미터 $\theta$를 찾고자 한다.

\[L(\boldsymbol{\theta}) = \sum \limits_{n=1} ^N L_n (\boldsymbol{\theta})\]

Gradient Descent(GD)의 종류를 아래와 같이 정리할 수 있다.

  • Stochastic GD: 하나의 샘플에 대해 그래디언트를 계산하고 파라미터를 업데이트한다.
  • Mini-batch GD: 작은 집합(mini batch)에 대해 그래디언트를 계산하고 파라미터를 업데이트한다. 대부분 이 방법을 이용한다.
  • Batch GD: 전체 데이터에 대해 그래디언트를 계산하고 파라미터를 업데이트한다.

이전까지 보았던 경사하강법은 Batch Gradient Descent에 해당한다. 식으로 나타내면 아래와 같다.

\[\boldsymbol{\theta}_{i+1} = \boldsymbol{\theta}_{i} - \gamma_i(\triangledown L(\boldsymbol{\theta}_{i}))^T = \boldsymbol{\theta}_{i} - \gamma_i \sum \limits_{n=1}^N (\triangledown L_n(\boldsymbol{\theta}_{i}))^T\]

모든 개별 함수 $L_n$ 에서 그래디언트를 구해 그 합을 구하는 것 자체도 오래 걸릴 뿐더러 간단한 식으로 나타낼 수 없는 경우도 있고, 훈련 데이터셋이 매우 클 경우에는 연산 비용이 매우 크다. 현실적 조건을 고려해보자면 CPU, GPU 메모리 용량이나 연산 시간 제한이 있다.

이를 직접 적용해 쓰기엔 무리가 있으므로, 그래디언트의 근사를 구해 실제 그래디언트와 유사한 방향으로 움직이게 할 수 있다. 모든 n에 대해 $L_n$ 의 합을 계산하지 않고, 무작위로 $L_n$ 의 부분집합을 뽑아 미니배치 경사하강법(mini-batch gradient descent)을 수행할 수 있다. 극단적인 경우 하나씩의 샘플에 대해서만 수행할 수도 있다(Stocastic Gradient Descent)

Stochastic Gradient Descent (SGD)

우리말로는 '확률적 경사하강법'이라고들 한다. (필자는 SGD라 부르겠다.) SGD는 경사하강법의 stochastic(확률적인) 근사이며, 당연히 경사하강법처럼 (미분 가능한 함수의 합으로 나타나는) 목적 함수를 최소화하는 방법이다.

정확한 그래디언트는 모르지만, 노이즈가 포함되어 있는 근사치는 알고 있다는 데서 단어 ‘Stochastic’이 쓰인다. 그래디언트 근사의 확률 분포를 제한함으로써, 이론적으론 여전히 SGD가 수렴할 것이라 보장할 수 있다.

전체 데이터의 부분집합을 취하는 것이 어떻게 경사하강법을 수렴하게 할까. ‘실제(true) 그래디언트의 변향되지 않은 추정(estimate)인 그래디언트’만 필요로하기 때문이다. Batch Gradient Descent 식의 $\sum \limits_{n=1}^N (\triangledown L_n(\boldsymbol{\theta}_{i}))$ 항 자체가 그래디언트의 기댓값의 경험적(empirical) 추정치였다. 따라서 기댓값의 다른 어떤 편향 없는 경험적 추정치(e.g. 데이터의 부분집합)도 경사하강법을 수렴시키기에 충분하다.

미니배치의 크기에 대해 생각해보자.

배치의 크기가 크면,

  • 장점
    • 파라미터 업데이트에서 분산을 감소시킴으로써, 그래디언트의 정확한 추정이 가능하다.
    • 비용과 그래디언트의 벡터화된 구현으로 말미암아, 매우 최적화된 행렬 연산이 가능하다.
    • 분산의 감소로 수렴이 더욱 안정적으로 이루어진다.
  • 단점
    • 앞서 밝혔듯, 그래디언트 연산이 매우 복잡하고 시간이 많이 든다.

반대로 배치의 크기가 작으면,

  • 장점
    • 추정을 빠르게 할 수 있다.
    • 내제된 노이즈 덕분에, 잘못 빠져들어간 local minima에서 빠져나올 가능성도 있다.

머신러닝에서 훈련 과정 동안 최적화는 훈련 데이터를 가지고 목적 함수를 최소화하며 이루어지지만, 훈련의 최종적 목표는 일반화 성능(generalization performance)를 높이는 것이다. 쉽게 말하면 훈련셋에 오버피팅도 피해야 하고, 굳이 목적함수의 정확한 최솟값을 찾을 필요는 없단 뜻이다. 그래서 미니배치를 통한 그래디언트 근사가 많이 쓰이고, 대규모 머신러닝 문제에서 효과를 보이고 있다.

arrow_upward arrow_downward
loading