논문

하루에도 수만개의 글자를 읽고 있습니다. 하루에도 수백장의 종이를 들춰 읽습니다.
이것은 그 읽기에 대한 일기입니다.

UFLDL Tutorial 4. Supervised Learning and Optimization – Debugging: Gradient Checking

http://deeplearning.stanford.edu/tutorial/

Supervised Learning and Optimization - Debugging: Gradient Checking

지금까지 우리는 objective function과 그 그래디언트를 손으로 계산해서 구현한 비교적 간단한 알고리즘을 다루었습니다. 또 그것을 MATLAB으로 구현하였고요. 앞으로 배우겠지만 신경망에서의 back-propagation과 같은 더 복잡한 모델을 다루기 위해서는 그래디언트 계산을 옮게 계산하는 것과 그것을 디버깅하기가 어렵기로 명성이 자자합니다. 어떨 때에는 버그가 미묘해서 코드가 마치 잘 작성되어 학습이 되고 있는 것처럼 보일 때도 있기 때문에, 실제로 버그가 있더라도 잘못된 것이 무엇인지 명확하게 보이지 않을 때가 많습니다. 이 시간에는 코드로 작성된 편미분 계산이 수치적으로 맞는지 점검하는 법과 코드가 정확하게 구현되었는지 점검하는 법을 알아보고자 합니다. 여기서 설명하는 대로 편미분의 점검이 이루어지면, 작성한 코드의 정확성에 대해서 한층 신뢰감이 높아질 것입니다.

이제 $J(\theta)$를 최소화하는 상황을 가정해봅시다. 이 예제에서는 $\theta \in \Re$$\textstyle J : \Re \mapsto \Re$를 사용합니다. 그리고 우리가 minFunc나 이미 구현된 다른 최적화 알고리즘을 쓰려고 한다면, $\frac{d}{d \theta} J(\theta)$이라고 알려진 어떤 함수 $g(\theta)$를 구현해두었을 것입니다.

어떻게 이 $g$가 정확하게 구현되었는지 점검할 수 있을까요?

편미분의 정의를 상기시켜봅시다.

$$\frac{d}{d\theta}J(\theta) = \lim_{\epsilon \rightarrow 0} \frac{J(\theta+ \epsilon) - J(\theta-\epsilon)}{2 \epsilon}$$

따라서 어떤 $\theta$값에 대해서 다음을 계산함으로서 수치적으로 편미분 값을 추정할 수 있습니다.

$$\frac{J(\theta+{\rm EPSILON}) - J(\theta-{\rm EPSILON})}{2 \times {\rm EPSILON}}$$

실제로 구현할 때에는, ${\rm EPSILON}$를 아주 작은 상수, 이를테면 $10^{-4}$정도로 지정하여 사용합니다. ${\rm EPSILON}$로 사용할만한 수의 범위는 굉장히 넓지만, $10^{-20}$처럼 지나치게 작은 값은 사용하지 않는 것으로 합니다. 오히려 roundoff 오차를 만들어낼 수 있기 때문입니다.

이제 $\frac{d}{d \theta} J(\theta)$를 계산하기 위한 어떤 함수 $g(\theta)$가 주어지게 되면, 그것을 다음을 이용해 점검할 수 있게 되었습니다.

$$g(\theta) \approx \frac{J(\theta+{\rm EPSILON}) - J(\theta-{\rm EPSILON})}{2 \times {\rm EPSILON}}$$

두 값이 서로 근사해야 하는 정도는 $J$가 어떤 식이냐에 따라 달려있습니다. 하지만 $\textstyle {\rm EPSILON} = 10^{-4}$로 가정하면 대부분의 경우, 왼쪽 오른쪽 식이 최소한 4 이상의 유효자리수를 가지게 될 것입니다.

이제 파라미터가 실수가 아니라 벡터 $ \textstyle \theta \in \Re^n $이고, $\textstyle J: \Re^n \mapsto \Re$ 인 경우로 확장해봅시다. 앞의 편미분 점검 과정을 $\theta$가 벡터일 때도 사용할 수 있도록 일반화할 것입니다. 여러 변수나 행렬에 대해 최적화를 하고 있다면 거의 저러한 파라미터들을 하나의 긴 벡터로 넣어 사용하고 있을 것입니다. 따라서 편미분을 점검할 때에도 같은 방식을 사용합니다. 이것은 예제에서 사용한 것이 아닌 다른 툴을 사용할 때에도 마찬가지로 적용될 것입니다.

마찬가지로 $\textstyle \frac{\partial}{\partial \theta_i} J(\theta)$를 계산하기 위한 식 $\textstyle g_i(\theta)$가 있다고 합시다. 이제는 각 $g_i$가 정확히 계산되었는지 알고 싶습니다. 여기서 $\textstyle \theta^{(i+)} = \theta + {\rm EPSILON} \times \vec{e}_i$라고 나타내어봅시다.

$$\vec{e}_i = \begin{bmatrix}0 \\ 0 \\ \vdots \\ 1 \\ \vdots \\ 0\end{bmatrix}$$

$\vec{e}_i$는 i번째 basis 벡터로 $\theta$와 같은 차원을 가지면서 i번째 위치만 1이고 나머지 부분은 0인 벡터입니다. 따라서 $\theta^{(i+)}$ 는 i번째 항을 제외하고는 $\theta$와 같고 i번째 항은 ${\rm EPSILON}$만큼 증가하였을 것입니다. 마찬가지로 $\textstyle \theta^{(i-)} = \theta - {\rm EPSILON} \times \vec{e}_i$를 정의하고 이를 i번째 항만 $\rm EPSILON$만큼 감소한 것을 나타낸다고 합시다.

이제 아래와 같이 비슷한 방법으로 $g_i (\theta)$를 점검할 수 있습니다.

$$g_i(\theta) \approx \frac{J(\theta^{(i+)}) - J(\theta^{(i-)})}{2 \times {\rm EPSILON}}$$

Gradient checker code

앞에서 배운 그래디언트 점검 방법을 연습하기 위해서 linear regression과 logistic regression에 적용하여 봅시다. 혹은 미리 작성된 ex1/grad_check.m를 이용할 수도 있습니다. 이 예제 파일에서는 무작위로 $i$를 선택하여 $\frac{\partial J(\theta)}{\partial \theta_i}$을 점검할 것입니다.


Tags:
Add a Comment Trackback