티스토리 뷰

이제 우리는 우리의 뉴런 네트워크를 위한 설계도를 가지고 있습니다. 어떻게 하면 이 네트워크가 숫자를 인식하도록 학습을 할 수 있을까요? 우리에게 필요한 첫번째는 학습 데이터 셋이라고 불리는 데이터 입니다. 우리는 MNIST 데이터 셋을 사용할 것 입니다. 이는 정확한 분석결과와 함께 손으로 쓰인 수만개의 숫자들을 스캔한 이미지를 가지고 있습니다. MNIST의 이름은 NIST에 의해 수집된 두개의 데이터 셋을 수정한 별도의 셋이라는 사실로 부터 지어졌습니다. NIST는 United States' National Institute of Standards and Technology의 약자 입니다. 아래 사진은 MNIST로 부터 가져온 몇장의 사진 입니다.



위에 보이는 것 처럼, 이 숫자들은 사실 이 챕터의 시작에서 보여드린 것과 같은 이미지입니다. 당연히, 우리의 네트워크를 시험할때에는 이 학습 셋에 있지 않은 이미지들을 사용할것입니다!


MNIST 데이터 셋은 두개의 부분으로 나뉩니다. 첫번째 부분은 학습 셋으로 사용될 60,000개의 이미지로 이루어져 있습니다. 이 이미지들의 반은 US Census Beureau 직원들과 반은 고등학생으로 이루어진 250명의 사람들로 부터 스캔한 이미지 입니다. 이 이미지들은 $28\times 28$크기의 흑백 사진입니다. 우리는 이것을 우리의 네트워크가 숫자를 인식하는것에 얼마나 잘 학습되었는지 평가하기 위해 사용할 것입니다. 좋은 성능 테스트를 하기 위해 테스트 셋은 원본 학습 데이터에 있던 사람과는 다른 250명의 사람들로 부터 가져왔습니다.(비록 모집단은 여전히 Census Bereau 직원들과 고등학생이지만요.) 이는 우리의 시스템이 학습하는 동안 보지 못한 사람들이 쓴 숫자들을 인식할 수 있는지 우리에게 확신을 줄 수 있도록 도와줄 것입니다. 우리는 학습 입력 데이터를 표시하기 위해 $x$라는 기호를 사용할 것입니다. 각각의 입력 $x$를 $28\times 28=784$차원의 백터로 생각하는것이 편할겁니다. 백터의 각 성분은 이미지의 각 픽셀의 명도를 나타냅니다. 우리는 $y=y(x)$로써 우리가 각 입력마다의 우리가 원하는 출력값을 나타낼겁니다. $y$는 10차원 백터입니다. 예를 들어, 6을 나타내는 특정한 학습 이미지 $x$에 대해 $y(x)=(0, 0, 0, 0, 0, 0, 1, 0, 0, 0)^T$가 네트워크로 부터 우리가 원하는 출력이 됩니다. $T$는 여기서 열 백터를 일반적인 행 백터로 바꿔주는 $transpose$ 연산이라는 것을 알아두세요.


우리가 원하는 것은 가중치와 $bias$를 찾아서 네트워크로 부터 나온 출력값이 모든 학습 데이터 $x$에 대해 $y(x)$의 값과 거의 같도록 하는 알고리즘을 만드는 것 입니다. 얼마나 우리가 이 목표를 잘 달성하였는지 수치로 나타내기 위해 우린 비용함수 라는 것을 하나 정의할것 입니다.


$$\begin{eqnarray}  C(w,b) \equiv\frac{1}{2n} \sum_x \| y(x) - a\|^2.\tag{6}\end{eqnarray}$$


여기 $w$는 네트워크의 모든 가중치($weight$)를 의미하고 $b$는 모든 $bias$, $n$은 학습 이미지의 총 갯수, $a$는 $x$가 입력으로 주어졌을때의 네트워크에서의 출력, 그리고 시그마는 모든 학습 이미지 $x$에 대한 값 입니다. 당연히 출력 $a$는 $x$, $w$ 그리고 $b$에 종속되어 있습니다. 하지만 이 공식을 간단하게 하기 위해서 아직 이 종속관계를 명확하게 밝히지 않았습니다. $\|v\|$라는 기호는 백터 $v$에 대한 길이만을 의미합니다. 우리는 이 $C$라는 함수를 이차 비용 함수라고 부릅니다. 이 함수는 mean squared error 또는 MSE라고 불리기도 합니다. 이차 비용 함수의 형태를 보니, $C(w, b)$는 시그마가 음수가 될 수 없기에 양수의 값만을 가진다는 것을 알 수 있습니다. 또한, $C(w, b)$는 $y(x)$가 모든 학습 데이터 $x$에 대한 출력 $a$와 비슷해 질 때 $C(w, b)\approx 0$ 이 됨을 알 수 있습니다. 그러므로 우리의 학습 알고리즘은 가중치와 $bias$를 잘 찾아서 $C(w, b)\approx 0$가 될 때 잘 학습되었다고 말할 수 있습니다. 반대로, $C(w, b)$의 값이 크다면 잘 학습되지 않은 것 입니다. 이는 많은 수의 입력 데이터에 대한 출력 $a$와 $y(x)$가 비슷한 값을 가지지 않음을 의미합니다. 그러므로 우리의 학습 알고리즘의 초점은 가중치와 $bias$에 대한 함수로써 $C(w, b)$의 값을 최소화 하는것 입니다. 다른말로, 우리는 비용함수의 값을 가능한 작게 만드는 가중치와 $bias$를 찾고싶은 것 입니다. 우리는 이를 기울기 하강 알고리즘이라고 불리는 알고리즘을 통해 구현할 것 입니다.


왜 비용 함수를 소개했을까요? 다른걸 다 떠나서, 우리는 첫째로 네트워크에 의해 정확히 판별되는 이미지에 관심있던것 아니었나요? 왜 비용함수와 같은 간접적인 수치를 최소화 하는것이 아닌 그 갯수 자체를 높이는것에 초점을 맞추지 않는것일까요? 문제는 정확히 판별된 이미지의 갯수는 네트워크의 가중치와 $bias$에 대한 부드러운 함수로 표현되지 않는다는 것 입니다. 대부분 가중치와 $bias$의 작은 변화를 만드는 것이 정확히 판별되는 학습 이미지의 갯수의 변화를 만들어 내지 못합니다. 이는 어떻게 향상된 성능을 얻기 위해 가중치와 $bias$를 바꾸어야 하는지 알아내는것을 어렵게 합니다. 만약 우리가 이차 비용 함수와 같은 부드러운 함수를 사용하게 된다면, 어떻게 비용적 측면에서 향상을 이끌어 내기 위해 가중치와 $bias$에서 작은 변화를 만들어야 할지 알아내기 쉬울것입니다. 이것이 우리가 비용함수의 최소화에 초점을 맞추는 이유입니다. 그리고 나중에 우리는 판변의 정확도에 대해서 검토하게 될겁니다.


우리가 부드러운 비용 함수를 사용하고 싶다고 이야기 하였는데, 여러분은 아마 왜 우리가 (6)번 공식과 같은 이차 함수를 선택했는지 궁금해 하실지도 모르겠습니다. 과연 우리가 원하는 목적에 맞는 선택일까요? 우리가 다른 비용함수를 선택하면 전혀 다른 가중치와 $bias$를 가지게 되지 않을까요? 이는 충분히 걱정할만한 부분입니다. 나중에 우리는 이 비용함수로 다시 돌아와서 몇개를 수정할겁니다. 그러나, 6번 식의 이차 비용 함수는 뉴런 네트워크에서 학습의 기초를 다지는데 큰 도움을 줍니다. 그러니 일단은 우리는 이 함수를 사용하도록 합시다.


요약하자면, 뉴런 네트워크에서의 우리의 목표는 이차 비용 함수 $C(w, b)$의 값을 최소화 할 수 있는 가중치와 $bias$를 찾는것 입니다. 이는 우량 조건 문제(역주: 문제의 답이 존재하고 그 해가 유일하게 결정될 수 있는 조건의 문제)입니다. 하지만 현재 우리에게는 이 목표를 이루는것을 흐리게 하는 여러가지 요소들이 있습니다. 가중치와 $bias$에 대한 이해, 시그모이드 함수, 네트워크 구조의 선택, MNIST, 기타 등등... 우리가 대부분의 저 요소들을 잠시 무시하고 함수 최소화 문제에만 집중함으로써 더 많은것을 이해할 수 있을것입니다. 일단 지금은 비용함수의 정확한 식, 뉴런 네트워크의 연결 기타 등등에 대한 모든것을 잊읍시다. 대신, 우리가 많은 변수를 가진 함수를 우리가 가지고 있고 우리가 그 함수의 값을 최소화 하고 싶다고 상상해 보려고 합니다. 우리는 최소화 문제와 같은 것을 풀기위해 사용될 수 있는 기울기 하강 알고리즘이라고 불리는 기술을 배울것 입니다. 그런뒤에 우리는 뉴런 네트워크에서 최소화 하고자 하는 특정한 함수로 돌아갈 것 입니다.


좋습니다, 우리가 $C(v)$라는 어떤 함수를 최소화 하려고 한다고 가정해 봅시다. 이 함수는 $v=v_{1}, v_{2}...$ 처럼 많은 변수에 대한 그 어떤 함수도 될 수 있습니다. 제가 이 함수가 그 어떤 함수도 될 수 있음을 강조하기 위해 $w$와 $b$를 $v$로 치환하였습니다. 우리는 더 이상 뉴런 네트워크의 맥락에서 생각하지 않을것입니다. $C(v)$를 최소화 하려면 $C$함수를 단지 두개의 변수를 가진 함수로 생각해 보는것이 도움이 되겠군요. 그 두개의 변수를 $v_{1}$와 $v_{2}$라고 부르도록 합시다.



우리가 하고싶은 것은 $C$가 최소인 곳을 찾는 것 입니다. 지금 위 함수에서는 당연히 눈을 돌려 $C$가 최소인곳을 어렵지 않게 찾을 수 있습니다. 제가 너무 간단한 예를 들어드린것 같군요! 일반적인 경우의 함수 $C$는 아마 많은 변수를 가지고 있을겁니다. 그리고 보통은 눈으로 그래프의 최소인곳을 찾기는 아마 불가능할겁니다.


이 문제를 해결하는 한가지 방법은 분석적으로 최소를 찾기위해 미적분을 사용하는 것 입니다. 우리는 미분을 통해 $C$가 극값을 가지는 곳을 찾을 수 있을 것 입니다. $C$가 한개 또는 두세개 정도의 변수만을 가지고 있다면 이 방법은 아마 잘 통할겁니다. 하지만 우리가 더 많은 변수를 가지고 있다면 이는 악몽같은 방법이 될겁니다. 그리고 뉴런 네트워크에서는 보통 더 많은 변수를 가지고 있습니다. 가장 큰 뉴런 네트워크는 엄청나게 복잡한 형태의 가중치와 $bias$에 대한 비용함수를 가지고 있습니다. 최소화를 하는 방법으로 단지 미적분을 사용하는것은 그냥은 먹히지 않을것 입니다!


()


그렇습니다, 미적분은 먹히지 않습니다. 하지만 운좋게도, 꽤 잘 먹히는 알고리즘을 이끌어 낼 수 있는 아름다운 유추 방법이 하나 있습니다. 우리의 함수를 하나의 계곡으로 생각하면서 시작해 봅시다. 여러분이 위의 그래프에서 눈을 찌푸리지 않았다면 그리 어렵지 않을겁니다. 그리고 계곡의 비탈면으로 구르는 공을 한번 상상해 봅시다. 우리의 일상에서의 경험은 공이 결국에는 계곡의 바닥으로 굴러갈것이라고 말해줍니다. 우리가 이 아이디어를 함수의 최소를 찾는데 사용할 수 있을까요? 우리는 상상속의 공의 시작점을 아무데나 고르고, 계속 바닥으로 공이 구르도록 움직임을 시물레이션 할겁니다. 우리는 $C$의 미분 계산을 통해 (또는 이계도함수) 이 시물레이션을 간단히 해낼 수 있습니다. 이 미분은 계곡의 모양에 대해 알기위해 필요한 모든것을 알려줍니다. 그러므로 어떻게 우리의 공이 구르게 될지도 알려줍니다.


제가 설명한것만 보면, 마찰 또는 중력 등을 고려해서 공의 움직임에 대한 뉴턴 방정식을 쓰는것은 아닐까 생각하실수도 있지만, 그렇게 까지 심각하게 공의 움직임을 유츄하지는 않을것입니다. 우리는 $C$를 최소화 하기 위한 알고리즘을 고안하고 있는것이지, 물리 법칙의 정확한 시물레이션을 하고자 하는것이 아닙니다! 공이라는 시각은 우리의 상상을 시물레이션 하기 위함이지, 우리의 생각을 구속하기 위함이 아닙니다. 그러므로 물리의 방대한 세부사항 전체를 파고들기 보단 우리 스스로에게 한번 물어봅시다. 만약, 우리가 하루동안 신이 될 수 있다면, 그리고 물리의 법칙을 우리가 스스로 만들 수 있다면, 공이 어떻게 굴러야 하는지 규칙을 정할 수 있다면, 어떤 움직임의 법칙을 골라야 공이 항상 계속의 바닥면으로 구르게 할 수 있을까요?


이 질문을 좀 더 명확히 하자면, 우리가 공을 $v_{1}$방향으로 작은 $\Delta v_{1}$만큼 움직이고 $v_{2}$ 방향으로 작은 $\Delta v_{1}$ 만큼 움직였을 때 무엇이 일어나는지에 대해 생각해 봅시다. 미분식은 $C$가 다음과 같이 변함을 보여줍니다.


$$\begin{eqnarray}   \Delta C \approx \frac{\partial C}{\partial v_1} \Delta v_1 +  \frac{\partial C}{\partial v_2} \Delta v_2.\tag{7}\end{eqnarray}$$


우리는 $\Delta C$가 음수가 되도록 하는 $\Delta v_{1}$과 $\Delta v_{2}$를 고르는 방법을 찾을겁니다. 즉, 계곡 아래로 공이 구를 수 있도록 하는 값을 찾을겁니다. 어떻게 그렇게 선택을 할 수 있는지 알아내려면 $\Delta v$를 $\Delta v\equiv (\Delta v_{1}, \Delta v_{2})^{T}$처럼 $v$에서의 변화량에 대한 백터로 정의하는것이 도움이 됩니다. 여기서 $T$는 $transpose$ 연산자로써, 열 백터를 행 백터로 바꿔줍니다. 또한 우리는 C의 기울기를 $\left(\frac{\partial    C}{\partial v_1}, \frac{\partial C}{\partial v_2}\right)^T$ 와 같이 편미분의 백터로 정의할 것 입니다. 그리고 우리는 이 기울기 백터를 $\nabla C$으로 표현할 것 입니다.


$\begin{eqnarray}   \nabla C \equiv \left( \frac{\partial C}{\partial v_1},   \frac{\partial C}{\partial v_2} \right)^T.\tag{8}\end{eqnarray}$


후에 우리는 $\Delta C$의 변화를 $\Delta v$와 기울기 $\nabla C$에 대해서 다시 정의할겁니다. 이것에 대해 알아보기 전에, 가끔 몇몇 사람들이 이 기울기에서 막힌다는 것을 알려드리고 싶군요. $\nabla C$라는 기호를 처음 만나게 되면, 사람들은 가끔 $\nabla$라는 기호에 대해 어떻게 생각해야 하는지 궁금해 하곤 합니다. 정확하게 $\nabla$이 의미하는 바는 뭘까요? 사실, $\nabla C$자체를 하나의 수학 기호로 봐도 무방합니다. $\nabla$는 단지 "이봐, $\nabla C$는 기울기 백터야"라고 말할때 쓰이는 기호의 일부분에 불과합니다. $\nabla C$가 예를들면 미분 연산자처럼 그것 자체로 하나의 의미를 가지는 어려운 경우도 있지만 우리는 여기서 이런 경우를 생각할 필요는 없습니다.


이 정의들과 함께, $\Delta C$에 대한 7번 식은 다음과 같이 다시 쓰여질 수 있습니다.


$$\begin{eqnarray}   \Delta C \approx \nabla C \cdot \Delta v.\tag{9}\end{eqnarray}$$


이 공식은 왜 $\nabla C$가 기울기 백터라고 불리는지에 대한 이유를 설명하는데 도움을 줍니다. $\nabla C$는 우리가 기울기값이라는것이 하는 일에 대해서 예상할 수 있다시피 $C$에서의 변화량들과 $v$에서의 변화량을 관련짓습니다. 하지만 이 방정식에 대한 정말로 흥미로운 점은 이 방정식이 $\Delta C$를 음수로 만들기 위해 $\Delta v$를 어떻게 골라야 하는지 우리에게 보여준다는 것 입니다. 특히, 우리가 다음과 같은 $\Delta v$를 선택했다고 해봅시다.


$$\begin{eqnarray} \Delta v = -\eta \nabla C,\tag{10}\end{eqnarray}$$


여기서 $\eta$는 작은 양수입니다.(학습율, learning rate라고도 불립니다.) 9번 방정식은 우리에게 $\Delta C \approx -\eta\nabla C \cdot \nabla C = -\eta \|\nabla C\|^2$임을 보여줍니다. $\| \nabla C\|^2 \geq 0$이므로 $\Delta C \leq 0$이고 10번식을 따라 $v$를 변화시킨다면 이는 $C$는 증가하지 않고 항상 감소함을 보여줍니다. (물론, 9번 공식에서의 근사치의 한계 내에서만) 이런 특징이 바로 우리가 원하던 것입니다! 그리고 우리는 우리의 기울기 하강 알고리즘에서 우리의 공을 위한 "운동 법칙"을 정의하기 위해 공식10번을 취할것입니다. 이 말은 즉슨, 우리는 $\Delta v$의 값을 계산하기 위해 10번 공식을 사용하여 $\Delta v$만큼 공의 위치 $v$를 움직일 것입니다.


$$\begin{eqnarray} v \rightarrow v' = v -\eta \nabla C\end{eqnarray}$$


그리고 나서 우리는 또 다른 움직임을 만들기 위해 이 개정된 규칙을 다시 사용할 것입니다. 만약 우리가 이것을 반복하면, $C$가 최소가 될때까지 감소하는 상태를 유지할 수 있습니다.


요약하자면, 기울기 하강 알고리즘이 작동하는 방법은 기울기 $\nabla C$를 반복적으로 계산하기 위함이며, 계곡의 바닥면으로 "떨어지는" 방향으로 움직이기 위함입니다. 우리는 이것을 이렇게 시각화 할 수 있습니다.



이런 기울기 하강 규칙은 실제 물리 움직임을 재생산 하지는 않음을 알아두세요. 실제 세계에서는 공이 운동량을 가지고 있어서 계곡의 바닥면을 가로질러 가게 합니다. 혹은 계곡의 꼭대기로 올라가게 할 수도 있습니다. 반대로, 우리가 $\Delta v$를 선택하기위한 규칙은 단지 "지금이야, 굴러가!"라고 말할 뿐입니다. 이는 여전히 최소를 찾기위한 좋은 규칙입니다.


기울기 하강을 정확하게 작동하도록 만들기 위해서는, 9번 공식이 꽤 좋은 근사치를 가지기 위해서는 중분히 작은 학습율 $\eta$을 선택할 필요가 있습니다. 그렇지 않다면, $\Delta C > 0$이라는 영 좋지 않은 결과를 맞이할 수 도 있습니다. 거기에다, 우리는 $\Delta v$를 매우 작게 변화시키기 때문에 $\eta$가 너무 작아지길 원하진 않습니다. 그렇게 되면 기울기 하강 알고리즘은 매우 느리게 작동할 것입니다. 실용적인 구현에서는, $\eta$는 보통 9번 식이 좋은 근사치를 보이기 위해서 다양한 값을 가집니다. 그러나 알고리즘이 너무 느리지는 않습니다. 우리는 나중에 이것이 어떻게 작동하는지 볼것입니다.


저는 $C$함수를 단지 두개의 변수를 가진 함수로써 이야기 하였을때 기울기 하강을 설명하였습니다. 하지만, 사실, $C$가 더 많은 변수를 가지고 있을때에도 이 알고리즘은 제대로 작동합니다. 함수 $C$가 $m$개의 변수 $v_{1}$, ..., $v_{m}$를 가지고 있는 함수라고 가정하여 봅시다. 그러면 $C$의 변화량 $\Delta C$는 $\Delta v=(\Delta v_1, ..., \Delta v_m)^T$라는 작은 변화에 의해 생산됩니다.


$$\begin{eqnarray}   \Delta C \approx \nabla C \cdot \Delta v,\tag{12}\end{eqnarray}$$


여기서 기울기 $\nabla C$는 다음과 같은 백터입니다.


$$\begin{eqnarray}  \nabla C \equiv \left(\frac{\partial C}{\partial v_1}, \ldots,   \frac{\partial C}{\partial v_m}\right)^T.\tag{13}\end{eqnarray}$$


두개의 변수를 가진 경우에 대해서, 우리는 다음과 같이 $\Delta v$를 고를 수 있습니다.


$$\begin{eqnarray}  \Delta v = -\eta \nabla C,\tag{14}\end{eqnarray}$$


그리고 우리는 우리의 $\Delta C$에 대한 12번 식이 음수가 될것이라는 것을 증명하였습니다. 이는 함수 $C$가 많은 변수를 가진 함수일때에도 다음과 같은 규칙을 계속해서 적용시키므로써 최소를 향한 기울기를 따라가는 방법을 제시하여 줍니다.


$$\begin{eqnarray}  v \rightarrow v' = v-\eta \nabla C.\tag{15}\end{eqnarray}$$


여러분은 이 규칙을 기울기 하강 알고리즘의 정의로써 생각할 수 있습니다. 이 규칙은 함수 $C$의 최소를 찾기위해 $v$를 반복적으로 바꾸는 방법을 알려줍니다. 그러나 이 규칙이 항상 옳게 작동하지는 않습니다. 몇몇의 부분들이 C의 최소를 찾는것으로 부터 기울기 하강 알고리즘을 작동하지 않게 합니다. 그 부분에 대해서는 후의 장에서 다루려고 합니다. 그러나, 실제로는 대부분의 상황에서 기울기 하강 알고리즘은 굉장히 잘 작동합니다. 그리고 뉴런 네트워크에서 이러한 비용함수를 최소화 하는 방법이 굉장히 강력하고 네트워크가 학습하는데 큰 도움을 줌을 알게될것입니다.


사실, 기울기 하강 알고리즘은 최소를 찾는데 있어 잘 최적화 된 방법입니다. $C$를 가능한 작게 만들기 위하여 $\Delta v$를 움직이려고 한다고 해봅시다. 이는 $\Delta C \approx \nabla C \cdot \Delta v$를 최소화 하는것과 같습니다. 우리는 움직임의 범위를 제한하여 $\epsilon > 0$인 작은 값에 대해 $\|\Delta v \| = \epsilon$가 되도록 하려고 합니다. 다른말로 하면, 고정된 값 만큼씩만 움직여서 $C$를 가능한 작게 하는 움직임의 방향을 찾으려고 하는것입니다. $\nabla C \cdot \Delta v$를 최소화 하는 $\Delta v$의 값은 $\Delta v = -\eta \nabla C$이고, $\eta = \epsilon / \|\nabla C\|$은 $\|\Delta v\|=\epsilon$라는 고정된 값에 의해 결정됩니다. 그래서 기울기 하강 알고리즘은 $C$를 즉시 감소시키기는 방향으로는 작은 움직임을 취하는 방법이라는 관점으로 생각할 수 있습니다.


연습

* 마지막 단락의 주장을 증명하여 보세요. 힌트: 만약 여러분이 코시-슈바르츠 부등식에 대해 익숙치 않다면, 이것에 익숙해 지는것이 큰 도움이 될 것 입니다.

* 저는 $C$함수가 두개의 변수를 가질때 혹은 더 많은 변수를 가질때의 경우에서 기울기 하강을 설명하였습니다. 만약 $C$가 한개의 변수를 가진다면 어떻게 될까요? 1차원의 경우에서 기울기 하강이 어떻게 되는지 기하학적으로 표현해볼 수 있나요?


사람들은 기울기 하강 알고리즘의 많은 방법들을 조사하였고, 실제 물리적인 공과 비슷한 방법들도 있습니다. 이러한 공을 모티브로 한 방법들은 몇가지 장점들을 가지고 있습니다. 하지만 또한 중대한 단점또한 가지고 있습니다. 바로 $C$의 이계도함수를 반드시 계산해야 한다는 것과 이 작업은 굉장히 많은 비용이 든다는것 입니다. 왜 이것이 많은 비용이 드는지 이해하기 위해선, 모든 이계도함수 $\partial ^2C/\partial v_j \partial v_k$를 계산해야 한다고 가정해 봅시다. 만약 백만개의 $v_j$가 있다면, 우리가 계산해야 할것은 1조개(백만의 제곱)이 될것입니다! 이는 계산하는데 엄청난 비용이 들어갑니다. 물론, 이러한 문제를 피하기 위한 꼼수가 있고 기울기 하강을 대체하기 위한 방법을 찾는것은 여전히 활발히 조사되고 있습니다. 하지만 이 책에서는 기울기 하강을 뉴런 네트워크를 학습하기 위한 주 접근방법으로 사용할 것 입니다.


어떻게 우리가 뉴런 네트워크를 학습하기 위해 기울기 하강을 적용할 수 있나요? 방법은, 6번 공식에서 비용을 최소화 하는 가중치와 $bias$들을 찾기위해 기울기 하강을 사용하는 것 입니다. 어떻게 이것이 작동하는지 이해하기 위해서, 변수 $v_j$를 가중치와 $bias$로 바꾸어 기울기 하강 업데이트 규칙을 관련지어 봅시다. 다른말로 하면, 이제 함수 $C$는 가중치와 $bias$를 변수로 가지며 기울기 백터 $\nabla C$는 이제 $\partial C/\partial w_k$와 $\partial C/\partial b_l$을 성분으로 가집니다. 이제 다시 기울기 하강 업데이트 규칙을 쓰면 다음과 같습니다.


$$\begin{eqnarray}  w_k & \rightarrow & w_k' = w_k-\eta \frac{\partial C}{\partial w_k} \tag{16}\\  b_l & \rightarrow & b_l' = b_l-\eta \frac{\partial C}{\partial b_l}.\tag{17}\end{eqnarray}$$


이 규칙들을 반복적으로 적용시킴으로써 우리는 "계곡의 아래로 구르기"를 할 수 있고 비용함수의 최소를 찾을 수 있습니다. 다른말로, 이는 뉴런 네트워크를 학습하기 위해 사용할 수 있는 규칙입니다.


기울기 하강 알고리즘을 적용시키기 위한 많은 과제들이 있습니다. 우리는 후의 장에서 이에 대해 깊게 다룰것입니다. 하지만 지금 저는 단 하나의 문제에 대해서만 언급하고 싶군요. 문제가 무엇인지 이해하기 위해, 6번 공식의 이차 비용 함수로 돌아가 봅시다. $C = \frac{1}{n} \sum_x C_x$의 형태를 가진 비용 함수는 각 학습 데이터 마다의 비용 $C_x \equiv \frac{\|y(x)-a\|^2}{2}$의 평균입니다. 실제로 기울기 $\nabla C$를 계산하기 위해서 각 입력 데이터 $x$마다의 기울기 $\nabla C_x$를 계산할 필요가 있습니다. 그리고 이를 평균을 내면 $\nabla C = \frac{1}{n}\sum_x \nabla C_x$가 됩니다. 불행히도, 입력 데이터들의 양이 많아지면 이를 계산하는데 굉장히 오랜 시간이 걸립니다. 그리고 학습은 매우 느리게 진행됩니다.


확률적 기울기 하강 알고리즘이라고 불리는 아이디어는 학습을 빠르게 하는데 이용될 수 있습니다. 이 아이디어는 무작위로 선택된 입력 데이터들의 작은 집합로 부터 $\nabla C_x$을 계산함으로써 $\nabla C$를 추정하는것 입니다. 이 작은 집합들의 평균을 냄으로써 실제 기울기 $\nabla C$의 값을 정확하고 빠르게 추정할 수 있고 기울기 하강과 학습을 빠르게 하는데 도움이 됩니다.


이 아이디어를 명확히 하자면, 확률적 기울기 하강 알고리즘은 무작위로 $m$개의 학습 데이터를 고르므로써 작동합니다. 무작위로 선택된 학습 데이터들을 소집단(mini-batch)라고 부르고 각 데이터를 $X_1, X_2, ..., X_m$라고 이름붙입니다. 소집단의 크기 $m$은 $\nabla C_{X_j}$의 평균이 $\nabla C_x$의 평균값에 근사치가 되기에 충분히 커야합니다. 이 말은 다음과 같습니다.


$\begin{eqnarray}  \frac{\sum_{j=1}^m \nabla C_{X_{j}}}{m} \approx \frac{\sum_x \nabla C_x}{n} = \nabla C,\tag{18}\end{eqnarray}$$$


두번째 시그마 합은 모든 학습 데이터에 대한 것 입니다. 좌변을 교체하면 다음과 같습니다.


$$\begin{eqnarray}  \nabla C \approx \frac{1}{m} \sum_{j=1}^m \nabla C_{X_{j}},\tag{19}\end{eqnarray}$$


이 식은 우리가 무작위로 선택한 소집단의 기울기를 계산함으로써 전체 기울기의 값을 계산할 수 있음을 보여줍니다.


이를 뉴런 네트워크에서의 학습으로 연결시키기 위해서, $w_k$와 $b_l$이 네트워크에서의 가중치와 $bias$를 의미한다고 가정합시다. 확률적 기울기 하강 알고리즘은 학습 데이터의 무작위로 선택된 소집단을 고르고, 그것들을 가지고 학습함으로써 작동합니다.


$$\begin{eqnarray}   w_k & \rightarrow & w_k' = w_k-\frac{\eta}{m}  \sum_j \frac{\partial C_{X_j}}{\partial w_k} \tag{20}\\    b_l & \rightarrow & b_l' = b_l-\frac{\eta}{m}  \sum_j \frac{\partial C_{X_j}}{\partial b_l},\tag{21}\end{eqnarray}$$


시그마 합은 현재 소집단에 있는 학습 데이터에 대한 것 입니다. 우리는 또 다른 소집단을 선택한 다음 그것을 가지고 또 학습을 합니다. 그리고 이것을 학습데이터가 바닥날때 까지 반복합니다. 우리는 이 한번의 반복을 세대(epoch)라고 부릅니다. 한 세대가 끝나면 또 한 세대를 반복합니다.


부수적으로, 가중치와 바이어스를 업데이트하는 소집단의 그리고 비용함수의 스케일링은 다양할 수 있습니다. (6)번 식에서 $\frac{1}{n}$로 전체 비용을 축소시켰습니다. 어떤 사람들은 $\frac{1}{n}$항을 빼서 평균을 내는 대신에 전체 비용을 그냥 모두 더합니다. 이런 방법은 전체 학습 데이터의 갯수가 몇개인지 사전에 알지 못할때 유용합니다. 이는 예를 들면 학습 데이터가 실시간으로 계속 생성되어 갯수가 늘어나는 경우가 있겠습니다. 그리고 비슷한 방법으로, 소집단 업데이트 규칙인 (20)번 식과 (21)번식에서도 $\frac{1}{m}$항을 뺄 수 있습니다. 이는 작은 변화를 만드는데, 학습률 $\eta$를 변화시키는 것과 같은 효과를 보입니다. 하지만 서로 다른 작업들 자세히 비교해야 할때면, 이 변화에 대해 자세히 보는것도 나쁘지 않겠군요.


우리는 확률적 기울기 하강 알고리즘을 여론 조사와 같다고 생각 할 수 있습니다. 전체 집단의 기울기를 구하는것 보다는 작은 소집단의 기울기를 구하는것이 훨씬 쉽습니다. 전체 투표율을 조사하는것 보다는 여론을 조사하는것이 훨씬 쉬운것과 같은 이치죠. 예를 들면 MNIST 처럼 $n=60,000$의 크기를 가지는 학습데이터를 가지고 있고 $m=10$의 크기를 가지는 소집단 을 고르면, 이는 $6,000$배가 빨리 기울기를 구할 수 있다는것을 의미합니다! 물론, 구한 값이 매우 정확치는 않겠죠. 통계적 편차가 존재할 것입니다. 하지만 완벽한 값을 구할 필요가 없습니다. 우리가 하고자 하는것은 전체 $C$의 값을 감소시키는 일반적인 방향을 구하고자 하는것이지, 기울기에 대한 정확한 계산을 할 필요는 없다는 겁니다. 실제로, 확률적 기울기 하강 알고리즘은 뉴런 네트워크를 학습시키는데 있어서 매우 강력하고 자주 쓰이는 기술입니다. 그리고 이는 우리가 이 책에서 개발할 여러 학습 기술들의 바탕이 됩니다.


연습

  • 확률적 기울기 하강 알고리즘의 극단적인 버젼은 우리가 소집단의 크기를 1로 사용할 때 입니다. 이 말은, 주어진 학습데이터 $x$에 대해, $w_{k} \rightarrow w_{k}\prime = w_{k} - \eta \partial C_{x}/\partial w_{k}$ 와 $b_{l} \rightarrow b_{l}\prime = b_{l} - \eta \partial C_{x} /\partial b_{l}$라는 식으로 가중치와 바이어스를 업데이트 하는것을 의미합니다. 그리고 나서 다른 학습데이터를 고르고 다시 규칙을 적용합니다. 이를 계속 반복합니다. 이 과정은 online, on-line, 또는 incremental 학습 이라고 알려져 있습니다. online 학습에서, 뉴런 네트워크는 한번에 하나의 학습데이터만을 가지고 학습합니다(사람이 그러한 것 처럼). 소집단의 크기가 20인(가정) 확률적 기울기 하강 알고리즘과 비교해서 이 방법의 장점과 단점이 무엇인지 이야기 해 보세요.

마지막으로, 기울기 하강 알고리즘이 처음인 사람들을 가끔 괴롭히는 부분에 대해서 이야기하면서 이 섹션을 마치도록 하겠습니다. 뉴런 네트워크에서 비용 $C$는 가중치와 바이어스들과 같은 많은 변수들에 대한 함수입니다. 이는 매우 고차원의 공간상의 표면을 그린다고 생각할 수 있습니다. 몇몇 사람들은 이런 생각을 합니다: "이봐, 나는 모든 이 추가적인 차원들을 시각적으로 봐야할 필요가 있어!". 그리고 이들은 걱정하기 시작합니다: "나는 5차원은 커녕 4차원도 생각할 수 없어!(또는 5백만...)". 이들이 놓친 실제 뛰어난 수학자들이 가지고 있는 어떤 특별한 능력이 있을까요? 물론, 답은 '아니오'입니다. 대부분의 전문적인 수학자들 또한 4차원을 시각화 하지 못합니다. 대신 그들이 사용하는 꼼수는 무엇이 일어나고 있는지를 표현하는 다른 방법을 개발하는 것 입니다. 이것이 바로 우리가 앞서 했던 것과 정확히 일치합니다: 우리는 $C$를 감소시키기 위해 어떻게 움직여야 하는지 알아내기 위해 $\Delta C$에 대한 수학적 표현을 사용하였습니다. 고차원에서의 상상을 잘 하는 사람들은 서로 다른 많은 기술들을 가지고 있는 그들만의 머릿속 도서관을 가지고 있습니다. 우리의 수학적 꼼수는 단지 하나의 예시입니다. 이러한 기술들은 아마 3차원을 시각화 할때 처럼 우리에게 익숙한 간단함을 가지고 있진 않을겁니다. 하지만 여러분이 이런 기술들을 가지고 있는 여러분만의 도서관을 짓고 나면, 아마 고차원에서의 상상도 손쉽게 할 수 있을겁니다. 저는 여기서 더 자세히 들어가진 않겠지만, 관심이 좀 생겼다면 뛰어난 수학자들이 고차원에서의 상상을 하기 위해 사용하는 몇몇 기술들을 여기서 확인해 볼 수 있습니다. 몇몇 기술들은 꽤 복잡하지만, 대부분은 직관적이고 접근하기 쉽습니다. 그리고 아마 누구라도 마스터 할 수 있을겁니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday