왜 분명히 배운 것들인데 왜 복습을 하는 것 조차 이틀이나 걸리는 것인가. 솔직히 지금도 헛깔린다. 아무튼 Artificial Neural Network(ANN)을 공부해보도록 하자.


ANN에서는 data들을 어찌어찌 처리하여 그 data에 대한 predicted value를 만들어낸다. 예를 들어, 간단하게 XOR 함수를 놓고 생각해보자. x1과 x2가 1이면 그 값은 0이 된다. 우리가 이것을 ANN을 통해 예측해보려고 한다. 그러면 x1과 x2가 각각 1이니까, 이 값들을 어찌어찌 하여 output을 0으로 혹은 1으로 추측해보려고 한다. 어떻게 추측을 할까? weight을 곱해서 알아보는 것이다. 

위의 그림에서 x1, x2는 1이고 w1, w2는 각각 x1과 x2에 대한 weight이다. (x1, x2)와 (w1, w2)의 dot product을 구하면 o1이 나온다. Artificial Neural Network에서 Neural이 위의 그림 저것이다. Neural Network는 저것들이 여러개 모였다는 것이다. 즉, 우리의 XOR 예를 가지고 생각해보자면, XOR를 예측하기 위해 여러개의 Neural Network를 만들었다고 보면 된다. Neural Network는 아래와 같은 형태를 띄게 된다.


위의 그림에서 notation부터 정리를 해보자. 우선 각각 원i에서 원j으로의 weight을 wij로 표시했다. 그리고 원은 1부터 6까지 있다. 그리고 원i에서 나오는 output을 oi로 표시했다. 자 위의 그림에서라면 우리는 x1과 x2의 XOR을 예측하기 위해 아래와 같은 일을 해야된다.

여기서 중요한 용어를 한번 정리해보자. 바로 Input layer, hidden layer, output layer이다. (사실 위의 식은 틀린 것이다. 중요한 과정을 하나 빼먹은 과정인데, 조금만 더 읽어보면 뭐가 빠졌는지 알 수 있다.)

여기서 Hidden layer는 무슨 말이냐면, 말 그대로 감춰진 layer라는 것이다. 무슨 일이 벌어지는지 모른다는 것이다. 여기서 Hidden layer는 하나 밖에 없지만, 실제로는 더욱 깊은(deep) 여러 층의 hidden layer가 있는데, 여기에서의 deep이 deep learning의 deep이라고 한다.


자, 자세한건 일단 제쳐두고 w13부터 w56까지 특정 값을 가지고 있다고 했을 때, 이제 우리는 x1과 x2만 있으면 o6를 구할 수 있다. 그러면 그 값이 0이나 1로 정확히 나올까? o6를 구하기 위해서 우리는 dot product를 input layer에서 hidden layer로 3번하고 hidden layer에서 output layer로 1번, 총 4번을 하는데, 그 dot product의 결과가 0이나 1로 딱 떨어질까? 그럴리는 거의 없다고 보면 된다. 그럼 어떻게 할까? 사실 우리는 지금까지 설명 안한 과정이 한 부분 있다. 그 부분을 포함하면 각 neural은 아래의 그림이 된다.


dot product 결과 z1을 Activation function에 집어넣어야 된다. 이 Activation function은 어떤 함수를 택하느냐에 따라 o1의 값이 바뀔 수 있는데, 가장 일반적으로 sigmoid function을 택한다. (어느 순간부터 가장 일반적으로 ReLu 함수를 많이 사용한다.)


sigmoid function은 그 값이 0과 1 사이(probability 구할 때 유용)라는 특징이 있는 "미분 가능한" 함수이다. ("미분 가능한"을 강조한 이유는 다음 포스팅 backpropagation을 설명할 때 같이 설명하겠다) 자 이제 우리는 o6를 구하는 올바른 식을 알아보자.

이제 o6는 무조건 0과 1사이의 값이 된다. 우리가 x1, x2를 가지고 위의 계산 과정을 거쳤을 때, 마지막 o6의 값이 0.8이 나왔다면 그 값은 1이 될 확률이 클 것이고, 0.2가 나왔다면 그 값은 0일 확률이 크다는 의미가 될 것이다.


우리가 지금까지 한 것은 ANN에서 forwarding이라고 한다. 즉 주어진 X의 값으로 그 ANN의 최종 output을 만들어내는 과정이다. 그렇다면 여기서 한 가지 질문을 해보면, 이거 한번 계산하면 정말 쓸만한 classifier가 되냐? 당연히 아니다. weight이 어떤 값이냐에 따라 결과는 아주아주 많이 바뀔 것이다. 그럼 우리는 가장 좋은 weight을 찾아야 된다. 그것은 어떻게 찾을까? cost function(J)을 통해 구하면 된다. 

여기서 y_hat은 우리가 구한 predicted value이다. 즉 predicted y와 실제 y의 차이를 구해서 제곱을 한 후 그것을 반으로 나눠준다는 것이다. 왜 절반으로 나누냐? 다음 포스팅 back propagation에서 위의 식을 미분할 것인데 그 때 제곱의 2가 밑으로 떨어지면서 1로 상쇄되면 계산하기 편하니까 이다. 이유가 못 마땅하다는 생각을 하는 사람이 많을 것이다. "수학이 뭐.. 편할 거 같은 숫자로 아무렇게나 하면 되는거야?" 이런 생각을 내가 했었고 그것 때문에 1/2를 곱해주는 이유에 대해서 꽤나 찾아봤었는데 결론은... 사실 뭘 곱해도 상관 없다 여기서는... 어짜피 우리한테 중요한 것은 두 개의 차이가 중요한 것이니까. 그 외의 상수는 뭐든 좋다는 것이다.


자 다시 본론으로 돌아가서, 이 cost function의 값이 가장 작도록 하는 weight을 찾아야 되는데, 가령 1부터 1000까지 일일이 weight을 설정하여 나온 값의 최소값을 구하면 아주 아주 아주 시간이 오래 걸릴 것이다. 그래서 우리는 여기서 미분을 한다. weight으로 미분을 해주는 것이다. cost function을 J로 놓으면 우리는 dJ/dw를 구해서 그 값이 0이 되는 방향으로 계속 weight을 update해줄 것이다. 이렇게 최소값을 찾는 과정을 gradient decent라고 한다.


마치 게임할 때 적절한 능력치를 올려줘서 balance를 맞춰주는 것처럼, 혹은 오디오에서 여러가지 음향 효과 버튼을 돌려서 최적의 소리를 세팅하는 것처럼, 각각의 weight(w13부터 w56까지)의 weight "버튼"을 적절히 돌려서 cost function이 최소화되는 그 바로 그 순간을 찾는 것이다.


위의 그림은 아래의 동영상의 일부를 캡쳐한 것이다. 정말 잘 만든 동영상이다.

https://www.youtube.com/watch?v=5u0jaA3qAGk


여기서 한가지만 더 쓰고 포스팅을 마치자. 만일 cost function이 아래와 같이 non-convex이면 어떻게 할까?

우리가 진짜 원하는 것은 global minimum인데 우리가 구한 값이 local minimum일 수도 있다는 이야기이다. 요약하면, 상관없다 이다. local minimum이여도 충분히 쓸만하다고 한다. 조금 어이없지만 그렇다고 한다. (마치 Naive Bayes에서 각 사건을 독립인 것처럼 전부 곱해버리는 데도 불구하고 실제로 꽤나 괜찮은 효율을 내는 것과 비슷하다.)


이것으로 이번 포스팅을 마치려고 한다. 다음 포스팅은 back propagation algorithm이다.

Posted by 빛나유
,