딥러닝을 공부하던 중 막상 코드로 짜보려니 햇갈리는 부분이 많아 결국 키보드 대신 펜을 잡기로 하였고, 펜으로 정리된 것을 이곳에 적어보려 한다.


딥러닝 관련 자료를 보면 많은 경우 이러한 그래프를 보게 된다. 


input layer는 입력 레이어, output layer는 최종 출력값을 내어주는 레이어다.

그런데 이를  식을 이용해서 코드로 구현하자니(손으로 써도 마찬가지..) 입력값만 봐도 8개이며 히든 레이어는 무려 9개씩 3층으로 이루어져 있다. 식도 길어질 대로 길어지고 나중에 알아보기도 힘들어진다.

이를 간단히 표현할 수 있는 방법이 바로 행렬이다. (비록 고등 교과과정에서 삭제되었지만....) 행렬을 간단히 소개하면 다음과 같은 개념이다.

일단, 행렬은 이와 같이 정의된다.

내용을 보면,  라는 행렬은 i개의 행과 j개의 열을 가지고 있다. 각 항은 i와 j값으로 표현된다.

프로그래밍 언어를 배웠다면 간단히 배열과 비슷한 형태라고 생각할 수 있다.


행렬과 행렬이 더해질 때는 i와 j 값이 같은 항끼리 더해진다. 

특이한 것은 행렬의 곱샘이다. 위키피디아의 정의는 다음과 같다.



예시는 다음과 같다.


따라서, 입력 레이어는 다음과 같이 행렬로 표현할 수 있겠다.



일단 입력 레이어는 행렬로 표현을 하였다. 그런데 우리가 원하는 식은  형태이다. 

여기서 행렬 연산의 특징이 이용된다. 위에서 소개한 행렬의 곱셈 연산 중 B*A 예시에 주목해 보자.

행렬의 정의에서 알 수 있듯이 앞에 행렬의 행이 1행이고, 뒤의 열이 1열일 때, 이를 곱하면 다항식이 도출된다.

다만, 곱할 때 앞 행렬의 행의 수와 뒷 행렬의 열의 수가 같지 않으면 (혹은 반대) 행렬의 곱샘은 정의될 수 없다.

이 점에만 주의하면 행렬로써 딥 러닝 그래프를 표현할 수 있다.



간단한 예제 코드를 살펴보며 행렬로 표현해 보자.



이 코드는 XOR을 학습하는 코드이며 tensorflow를 이용하였다.


XOR을 수행하기 위해서는 2가지의 값이 필요하다. train.txt 에는 해당되는 데이터가 저장되어 있다.


코드에서 6, 7번째 줄이 이 데이터들을 읽어와 x_data와 y_data에 저장해 주는 역할을 한다.


코드의 15번째 줄부터 22번째 줄까지를 보자. 


이부분이 weight값을 행렬로 생성하는 곳이다. tf.random_uniform 함수는 제일 처음 인자의 형태로 행렬을 만들고, 각 항들을 2번째 3번째 인자 사이의 값들 중 임의의 값으로 채운다.

즉, 15번째 줄은 2*5 행렬을 생성하고, 각 항들을 -1부터 +1 사이의 값들 중 임의의 값으로 채운다는 것을 의미한다


처음 2*5 행렬을 생성한 이유는 입력 레이어에서 입력받는 값이 2개임으로 1*2 행렬을 만들어 전달하기 때문이다.

행렬을곱할 때 앞 행렬의 행의 수와 뒷 행렬의 열의 수가 같지 않으면 (혹은 반대) 행렬의 곱샘은 정의될 수 없기 때문이다. 


이제 33번째 줄을 보자. 입력값인 X행렬과 w1행렬을 곱하고, 바이어스 값을 더한 후 이에 대해 relu 연산을 수행한다.

괄호 안쪽부터 차례대로 따라가보자.


우선 행렬의 곱을 수식으로 나타내면 다음과 같다.

이를 연산하면 다음과 같다.



결과적으로 열의 갯수가 5개인 행렬이 생성된다.


다음으로 바이어스 값을 더하게 된다. 바이어스 값은 24번째 줄에서 열의 갯수가 5개인 행렬로 정의되어 있다.

앞서 곱연산 후 나온 행렬의 크기가 1*5임으로 각각의 식에 바이어스 값을 더하려면 바이어스도 1*5 크기여야 한다.


결국 덧샘 연산까지 마친 후 도출되는 행렬은 열이 5개인 행렬이다. 즉 1*5인 행렬이다. 1*2 행렬과 2*5 행렬을 연산하여 1*5 행렬을 얻어낼 수 있게 되었다. 

더불어  형태의 식도 얻을 수 있게 되었다.(물론 연산중에는 실제 값들이기때문에 계산이 완료된 상수값이다)


34~40번째 줄은 각각 16~22 번째 줄과 25~31번째 줄의 weight 와 바이어스 값에 대해 비슷한 연산을 수행한다.

그렇게 출력 레이어 직전에는 100개의 계산결과가 나오게 된다. 그리고 마지막 출력 레이어에서 이를 곱연산을 통해 모든 항을 더한 값을 출력한다.


딥러닝에서는 위와 같이 상당히 많은 weight 와 바이어스 값들을 이용한다. 이때문에 1차식으로 일일히 이를 구현하는것은 노가다도 그런 노가다가 없으며, 나중에 코드를 다시 볼 때에도 상당히 불편해진다. 

어찌된 이유든 딥려닝에서는 행렬을 사용하여 코드를 구현하고, 결국 수학을 모르면 코드를 짜다가도 햇갈린다;;





혹여나 이글을 읽으시는 분들은 햇갈리실 일이 없길 바라며, 서술 중 잘못된 부분이 있으면 지적 부탁드립니다ㅎㅎ

'AI' 카테고리의 다른 글

Pycharm 원격 빌드 설정하기  (8) 2016.07.25
딥러닝과 행렬  (4) 2016.06.26
Windows 10 build 14332 에 TensorFlow 설치하기  (12) 2016.05.09
  1. 뚜비뚜밥 2016.07.21 17:54

    딥러닝에서 행렬이 왜 그렇게 중요한지 이해하는데 정말 한방에 이해가 되는 좋은 글인것 같습니다! 덕분에 공부하는데 많은 도움이 되었네요^^ 그런데 한가지 궁금한 점이 있습니다. 40번 라인까지의 계산 결과로는 1x5 행렬이 생성되고, 42, 43 라인을 통해 1x1의 cost 가 계산된 다음 이를 45, 46, 47번 라인에서 학습하는데, 이 때 출력 이전까지의 행렬 크기가 어떻게 100이 되는지가 궁금합니다. 그냥...학습하면 100개의 계산 결과값이 나오는 건가요 아님 출력 결과의 차원을 예측하기 위한 계산 식이 있는 것인지요? 본 글의 취지와는 살짝 어긋나긴 하지만 궁금해서 이렇게 여쭤봅니다 ㅎㅎ

    • ghatdev 2016.07.21 19:26 신고

      출력 직전의 레이어인 L8의 레이어를 보면 W가 10*10의 행렬로 정의되어 있습니다.(21번째 라인을 참고하세요) 또한 이전 레이어인 L7에서 넘어온 행렬의 크기도 10*10입니다. 행렬을 곱할때 크기가 같은 행렬을 곱하게 되면 도출되는 행렬도 같은 크기가 됩니다. 따라서 L8레이어 만 보면 100개의 w_i*x_i + b_i 식을 가지고 있습니다. 이를 10*1크기의 행렬과 곱을 하게 되면 행렬의 곱연산 이후 1*1 크기의 행렬이 도출되게 됩니다.
      원하시는 답이 되었나요?ㅎㅎ

    • 뚜비뚜밥 2016.07.21 19:33

      아! 수식을 위주로 보다보니 그부분이 떡 하니 있는데도 못봤네요ㅎㅎ 감사합니다!

    • ghatdev 2016.07.21 19:35 신고

      넵ㅎㅎ 부족한 글 읽어주셔서 감사합니다!

+ Recent posts