[기계학습심화] 11. 딥러닝 (2) - Neural Network & Back Propagation
Neural Network
이제 딥러닝의 기본적인 아이디어인 인공 신경망과 역전파(back propagation) 에 대해 정리해보려고 한다.
사실 딥러닝도 기존의 전통적인 기계학습과 크게 보면 다르지 않다.
전통적인 기계학습 파이프라인을 간단하게 정리해보면 데이터를 모아서 전처리하고, 해당 데이터를 인풋으로 넣었을 때 원하는 결과를 내보내는 함수를 찾기 위해 함수의 형태를 정의하고, 함수의 계수를 찾는 문제였다.
뉴럴 네트워크는 여기에서 함수의 형태만 바꾼 것이다.
전통적인 기계학습에서는 간단하게 선형 함수를 사용했다면, 뉴럴 네트워크에서는 입력 데이터에 대해 리니어 매핑을 해주고, 논 리니어 매핑을 해준다. 이 결과를 다시 어떤 함수의 입력으로 넣어서 리니어 매핑하고, 논 리니어 매핑하고 내보내고, 다시 그 결과를 다른 함수에 넣어서 리니어 매핑과 논 리니어 매핑해주기를 반복하면서 함수를 중첩해 나가는 것이다.
그래서 중첩되어지는 함수 하나 하나는 우리가 잘 아는 간단한 형태의 함수이다.
각각의 함수에 대해서 f(x; w1), g(x; w2), h(x; w3) 가 있어서 이 함수들이 중첩되어 뉴럴 네트워크를 형성한다면 우리가 학습할 대상은 w1, w2, w3 와 같은 각 함수의 계수가 된다.
그리고 이 계수들을 튜닝하면서 학습하고, 최종적으로 f - g - h 를 합성한 F(x) 가 최종 모델이 된다.
지금까지 기계학습이 잘 안되었던 이유는 어떤 함수를 써야할 지 몰라서 막혔었다.
함수를 잘 골라야 under fitting, over fitting 문제를 피할 수 있는데, 데이터가 어떻게 생겼는지 알 수 없기 때문에 모델을 정할 수 없는 것이다.
하지만 '뉴럴 네트워크' 라는 형태의 함수를 발견하면서 성능이 폭발적으로 증가하게 되었다.
그리고 뉴럴 네트워크에서는 중첩되어지는 각각의 함수를 가리켜 '레이어' 라고도 표현한다.
데이터가 함수를 통과하면서 중첩되는 것을 레이어를 통과하는 것으로 보는 것이다.
그리고 하나의 거대 모델을 만드는 것은 이 레이어들을 켜켜이 쌓는 것으로 표현하기도 한다.
딥러닝 아이디어는 뇌를 구성하는 뉴런에서 나왔다.
뉴런은 핵에서 전기 신호를 받아 저장하고 있다가 액손으로 전달하며, 마일린이 액손을 감싸 보호하고 있다.
그리고 이런 뉴런 대략 10조개가 모여서 하나의 거대한 뇌를 구성한다.
뉴런에서 많이 쓰이는 부분은 연결성이 강해져서 신호가 점점 더 강해지고, 자주 쓰이지 않는 부분은 연결성이 약해져서 신호가 점점 약해지고 잘 활성화되지 않는다고 한다.
그리고 이런 뉴런의 구조를 본따서 만든 것이 인공 신경망이다.
하지만 그렇다고 인공 신경망이 실제 뇌처럼 동작하는 것은 아니고, 모양만 본따서 만든 것이다.
근데 본따서 만들어봤더니 잘 되더라.. 한 것이다.
인공신경망을 조금 더 들여다보면, 신경망에서 동그라미는 데이터를 나타내고, 선 하나 하나는 매트릭스를 나타낸다.
그래서 X 라는 데이터가 w1 이라는 매트릭스를 거쳐 σ(w1 x) 형태의 함수가 된다.
이때 w1 x 는 리니어 매트릭스이고, 시그마는 activation function 이라는 non linear 함수이다.
이렇게 하나의 데이터에 리니어 함수와 논 리니어 함수를 거치면 그 다음 계층에 데이터가 나온다.
그리고 이 데이터에 대해 다시 w2 매트릭스를 적용하고, non linear 함수를 적용하고
그 결과에 대해 다시 w3 매트릭스를 적용하고, non linear 함수를 적용하고,
그 결과에 대해 다시 w4 매트릭스를 적용하고, non linear 함수를 적용한 것이 최종 결과 Y 가 된다.
(이렇게 리니어와 논 리니어 함수를 적용한 '한 세트'를 가리켜 하나의 레이어라고 보통 표현한다.)
(그런데 강의록을 읽어보면 위 동그리마가 하나의 뉴런으로서 '함수' 역할을 한다고 묘사하는 것 같아서 헷갈린다.
만약 간선이 함수라면 맨 왼쪽에서 하나의 동그라미에 w1 을 곱한 결과가 어떻게 그 다음 5개 동그라미로 퍼지는 것일까?
동그라미 하나는 벡터의 원소를 나타내는 걸까?
강의록 설명을 따라 동그라미를 함수로 보고, 그 함수의 출력 결과를 그 다음의 5가지 함수에 보낸다고 생각하면 또 이해가 되는 것 같은데.. 뭔가 감이 잘 안 온다.)
즉, 전체 함수를 식으로 표현하면 F(x) = h( g( f(x) + b ) + b ) + b 와 같은 식으로 합성함수로 나타낼 수 있다.
그리고 모델을 학습시킨다는 것은 각각의 h, g, f 함수 매트릭스 w3, w2, w1 을 학습시키는 것과 같다.
각각의 w를 학습시킬 때는 지금까지 학습시킨 방법과 비슷하게 학습시킨다.
먼저 초기 w 값들은 모두 랜덤하게 지정해두고,
F(X) - Y 를 계산하여 Loss를 구한 뒤에, Loss 가 줄어드는 방향으로 w를 수정해 나가는 것이다.
이때 학습 대상이 하나의 w가 아니라 w1, w2, w3, w4 로 많은 것이 차이점이다.
w1 을 학습시키는 과정은 다음과 같다.
경사하강법 아이디어와 동일하게 현재 n번째 w1 벡터에서 Loss 함수를 w1 으로 미분한 방향의 반대방향으로 learning rate 를 곱해준 만큼 이동하여 n+1 번째 w1 벡터를 만든다.
이 과정을 w1 ~ w4 까지 반복해서 n+1 번째 w 값을 구하는 것이다.
그리고 이 전체 과정을 학습 데이터 전체에 대해 1번 반복하면 이를 가리켜 1 epoch 라고 부른다.
이 에포크를 수백, 수천번 반복하면 점점 w 값이 조정되면서 모델이 학습된다.
결론적으로 뉴럴 네트워크도 함수의 형태만 합성함수 꼴로 다를 뿐, 기존의 전통적인 기계학습과 학습 방법 결은 동일하다.
뉴럴 네트워크를 학습시키는 방법은 크게 2가지 단계가 있다.
첫 번째는 inference (추론) 단계이고, 다음은 Learning (학습) 단계이다.
추론 단계는 forward propagation 이라고 하고, 현재 w 파라미터 값들을 기준으로 F(x) 를 구하는 과정이다.
먼저 입력데이터가 들어오면 입력데이터를 f1, f2, f3 함수에 각각 넣어 f1(x), f2(x), f3(x) 를 구한다.
(동그라미는 함수다..?)
그리고 각각의 f(x) 출력값은 벡터형태로서 그 다음 함수의 입력으로 들어간다.
그 다음 함수를 g 라고 할 때, 그 다음 레이어에서는 4개의 g 함수가 존재한다.
각각의 함수를 적용한 결과는 다시 다음 레이어의 입력으로 들어가기를 반복한다.
이렇게 최종적으로 Y 값을 구하면 inference 가 끝난다.
이제 이 추론 결과를 토대로 각각의 함수들을 학습시켜야 한다.
즉, 각 atomic function 의 파라미터를 변경해야 한다.
Back Propagation
추론의 다음 단계인 학습 단계에서는 반대로 Back propagation(역전파) 을 통해 각각의 파라미터를 학습한다.
역전파는 추론 단계에서 구한 값과 실제 값 사이의 차이, 즉 로스를 구하고, 미분을 해서 미분의 반대 방향으로 w 값들을 업데이트하는 것을 말한다.
예를 들어 위 그림과 같은 f(x, y, z) 함수가 있다고 해보자.
f는 1차원 데이터 3개를 받는 파라미터를 갖고 있으며, 그 연산결과는 x * y + z 이다.
이제 이 최종값 f 를 Loss 라고 가정하고, 파라미터를 업데이트를 한다고 해보면,
파라미터를 업데이트 하기 위해서는 로스를 각 파라미터에 대해 미분한 값들이 필요하다.
이때 위 그림과 같이 주어진 함수를 3개의 레이어로 구성된 뉴럴 네트워크처럼 생각해보자.
그리고 각 레이어와 레이어 사이에 이렇게 f, g 라는 함수를 둬보자.
그러면
g = x * y
f = g + z
로 표현할 수 있다.
이때 위 그림과 같이 g는 x, y 에 대해서 미분할 수 있고, f 는 g와 z 에 대해 미분할 수 있다.
그리고 f 는 Loss 처럼 생각하기로 했으므로 이 값들을 조합하면 Loss 함수 f 에 대한 x, y, z 의 미분값을 얻을 수 있다.
Loss 를 x 로 미분한 것은 (Loss 를 g로 미분한 것 * g를 x로 미분한 것) 이고,
Loss 를 y 로 미분한 것은 (Loss 를 g로 미분한 것 * g를 y로 미분한 것) 이다.
이때 둘 다 Loss 를 g로 미분한 값이 공통으로 들어가고, 레이어의 관계로보면 다음의 관계와 같다.
두번째 레이어와 세번째 레이어 사이의 관계인 것이다.
따라서 로스와 x 사이의 미분값을 구하기 위해서는 먼저 로스와 g 사이의 미분 (뒷 레이어끼리의 관계) 가 먼저 필요하므로 뒤에서 미분값을 구해놓고, 그 값을 앞으로 가져오면서 앞의 미분값을 구할 때 활용하는 것이다.
그래서 위 그림과 같이 로스를 x로 미분한 값을 구할 땐 앞서 구해둔 '로스를 g로 미분한 값'을 현재 레이어에서 보고 있는 'g를 x로 미분한 값'에 곱하여 구한다.
g를 x로 미분한 값은 y 였고, f를 g로 미분한 값은 1이므로, 최종적으로 f 를 x로 미분한 값은 y 가 되어 y 값 5가 그 다음 x의 값이 된다.
같은 방식으로 y, z 를 구하면 위 그림과 같이 -3, 5, 2 로 시작했던 파라미터 값이 5, -3, 1 로 업데이트 된다.
정리하면 역전파는 결국 체인 룰이다.
미분을 연쇄적으로 할 수 있다는 점을 이용하여 인접 레이어간의 미분값을 구해서 저장해두고, 이전 레이어로 그 값을 넘겨 이전 레이어부터 최종 결과까지의 미분값을 누적곱으로 계산하는 것이다.
이때 역전파를 사용하려면 모든 함수는 반드시 미분가능해야 한다.
미분가능한 함수라는 전제가 없으면 미분의 연쇄를 사용하는 역전파 아이디어 자체를 적용할 수 없다.
이번엔 실제 뉴럴 네트워크와 비슷하게 데이터가 벡터와 행렬의 형태인 경우를 살펴보자.
위 그래프는 아래 식 형태의 함수를 나타낸다.
W 와 x 를 행렬 곱하고, 그 결과에 대해 L2 norm 을 구한 것이 f 이다.
이 f에 위 그림에서 보이는 빨간색 데이터를 넣어 forward propagation 하여 추론을 했다고 해보자.
이 0.2285 라는 값이 최종적으로 구한 Loss 라고 할 때, 역전파 기법으로 기존 W, x 파라미터를 업데이트 해보자.
벡터와 행렬에서 미분을 할 때는 그 각각의 원소 별로 미분을 해주면 된다.
따라서 우리가 찾을 값은 W의 i, j 번째 원소별 미분값, x 의 i 번째 원소별 미분값이다.
먼저 기존의 f 를 q 라는 중간 함수를 이용하여 쪼개 표현하면 위와 같이 쪼개서 표현할 수 있다.
그러면 위 식에서 n = 2 이므로 q는 q1, q2 2개의 값으로 구성된 벡터로 볼 수 있고,
f는 f(q) 로서 q1 과 q2 각각의 제곱의 합으로 볼 수 있다.
그리고 각각의 쪼개진 f, q, w, x 간의 미분값을 조합하면 f - w, f - x 간 미분값을 얻어낼 수 있다.
일단 인접해있어서 한번에 미분값을 구할 수 잇는 것들을 구해보면 위와 같다.
qk 를 Wij 로 미분한 것은 q 를 구성하는 각각의 원소를 Wij 로 미분한 것과 같다.
이를 W11 에 대해서 식을 세워보면
이렇게 작성할 수 있다.
w11 을 변화시켰을 때, q가 변하는 양은 q1 과 q2가 변하는 양의 합으로 표현한다.
우선 L2 norm 계산값을 그대로 f 로 가져가기 때문에 L2와 f 사이의 미분값은 1이다.
다음으로 f(q) 식은 위와 같이 표현되기 때문에, f를 qi 로 미분한 값은 2qi 가 된다.
(나머지 q 성분은 모두 상수 취급되어 사라짐)
따라서 기존 qi 값을 모두 두배하여 행렬로 만든 것이 q의 미분 값이 된다.
다음으로 f를 w로 미분한 값을 구하기 위해서 q와 w 에 대한 미분을 구해야 한다.
q를 W11 에 대해서 미분한 값을 구한다고 하면, q1 을 w11 으로 미분한 것과 q2를 w11 으로 미분한 것을 찾아주면 된다.
그래서 f 를 w11 으로 미분한 값은 0.38 이 나온다.
이런식으로 w12, w21, w22 를 모두 구하면 위 그림에서 파란색 영역과 같이 W 에 대한 미분값이 나온다.
같은 방식으로 x1, x2 에 대한 미분값도 위와 같이 구해줄 수 있다.
다만 위 Wx 에서 x는 데이터이므로, 학습 대상이 아니기 때문에 업데이트를 안하고 무시하면 된다.
나머지 W 는 학습의 대상이므로 미분값을 기반으로 경사하강법을 적용해서 업데이트를 해주면 된다.
(지금은 단순히 미분값만 구했지만, 부호를 반대로 바꿔서 learning rate를 곱한다음 기존 값에 더해주면 될 것이다.)
그리고 이렇게 연산자와 변수의 연산 과정을 그래프로 표현한 것을 Computational Graph 라고 부른다.
L2-Loss 의 computational graph 는 그림과 같이 x - y 연산을 먼저 하고 -> 제곱(square) 하는 과정으로 표현한다.
뒤에서 다룰 activation 함수로 쓰이는 시그모이드와 렐루의 computational graph 는 그림과 같다.
뉴럴 네트워크에서 역전파를 정리하면,
Y 라는 추론 결과값을 실제 값은 Y* 와의 차이를 구해서 L(W) 를 정의하고 (위 식에서는 L2-norm 사용)
경사하강법을 통해 W를 업데이트 할 때는 역전파를 통해 위와 같이 연쇄법칙을 적용하여 W를 업데이트 한다.
(그런데 W를 업데이트 하는 것이 목적인데 왜 X 로 미분했을까? W로 미분해야 하는 것 아닌가?)
GPT 말로는 W로 미분하는 것이 맞다고 한다.
그리고 Y 에서부터 X를 향해 가면서 체인 룰에 따라 미분 값을 구하면서 업데이트 하므로, 그 중간 중간에 미분값을 구해서 레이어에 저장해뒀다가 이전 레이어의 미분값을 계산할 때 연쇄적으로 적용한다.
지금까지 뉴럴 네트워크의 개념과 뉴럴 네트워크 함수를 학습시키기 위한 역전파 방법에 대해 정리하였다.
다음 글에서는 뉴럴 네트워크 중 Convolutioinal Neural Network 에 대해 알아보면서 뉴럴 네트워크 기반의 이미지 분류 모델 예시를 정리해보고자 한다.