Books/밑바닥부터 시작하는 딥러닝1

[Books] 밑바닥부터 시작하는 딥러닝 1 시작하기

언킴 2022. 3. 6. 21:27
반응형

밑바닥부터 시작하는 딥러닝1을 리뷰합니다.

 

밑바닥부터 시작하는 딥러닝(이하 밑시딥)1은 파이썬을 시작하고, 딥러닝에 관심을 가졌다면 필수적으로 읽고 가야하는 책이라고 생각한다. 밑시딥 시리즈는 딥러닝 패키지를 사용하지 않고 딥러닝을 밑바닥 구현부터 시작하기 때문에 딥러닝의 구조를 하나하나 파악할 수 있는 아주 좋은 책이다. 이 글에서는 밑시딥1을 읽고 지극히 개인적으로 중요하다고 생각하는 부분을 정리할 것이기 때문에 일부 내용이 빠져있을수도 있다. 

 

밑시딥1은 밑바닥부터 구현하는 것을 목표로 두기 때문에 외부 라이브러리를 최소한만 사용한다. (numpy, matplotlib은 예외적으로 사용한다.) 기본적인 산술 연산 및 자료 구조와 같은 내용(1장)은 여기 코드를 참고하길 바라며, 본 글에서는 넘어가고, 2장의 내용부터 작성한다. 

 

 

퍼셉트론(Perceptron)

퍼셉트론(Perceptron)은 인공신경망(Artificial Neural Network)의 한 종류로 가장 초기 딥러닝 모델이라고 이해하면 된다. 퍼셉트론의 신호는 흐름을 만들고 정보를 앞으로 전달한다. 일정 임계값을 넘으면 1로 출력하고, 임계값에 도달하지 못한다면 0을 출력한다. 

 

위 그림은 가장 간단한 형태의 퍼셉트론 구조이다. $x_1, x_2$는 입력 신호를 의미하고, $y$는 출력 신호, $w_1, w_2$는 가중치를 의미한다. 또한, 원으로 표시된 부분을 하나의 노드(node)라고 부른다. 퍼셉트론을 수식으로 나타내면 다음과 같이 정의할 수 있다. 

 

$ y = \begin{cases} 0 \ (w_1x_1 + w_2x_2 \le \theta) \\ \\ 1 \ (w_1x_2 + w_2x_2 > \theta ) \end{cases}$

 

$\theta$는 임계값을 의미한다. 총합인 y의 값이 임계값보다 크면 1을 출력하고, 아니라면 0을 출력한다. 

 

AND, NAND, OR gate

위와 같은 논리회로는 AND, NAND, OR gate가 존재한다. AND gate는 $x_1, x_2$ 모두 1일 경우에만 1을 출력하고, 나머지 경우에는 0을 출력한다. NAND gate는 AND의 반대를 의미하며 모두 0일 경우에만 0을 출력하고, 나머지 경우에는 1을 출력한다. 마지막으로 OR gate는 1이 하나 이상이면 1을 출력하는 것이다. 둘다 0일 경우에만 0을 출력하게 된다[코드]

 

 

 

하지만 AND, NAND, OR 의 3가지 논리 회로로 XOR과 같은 논리 회로는 퍼셉트론으로 구현할수가 없다. 논리회로는 결정 경계(Decision boundary)가 선형으로 되어있기 때문에 아래와 같은 그림을 구분지을 수가 없다. 

 

 

 

오른쪽의 세모로된 경우 선형 함수로는 구별할 수 없을 것이다. 그렇기에 다층 퍼셉트론(multi-layer perceptron)이라는 개념이 나오게 되었다. 다층 퍼셉트론은 층을 여러개로 쌓아서 선형을 비선형으로 변환해주는 것이다. 아래와 같이 선형이 아니라 비선형으로 결정 경계를 생성하게 되면 XOR 문제를 해결할 수 있게 된다.[코드] [참고자료]

 

 

신경망(Neural Network)

퍼셉트론을 여러 층으로 쌓게 되면 신경망 모형이 된다. 가장 맨 왼쪽이 입력층(input layer), 맨 오른쪽이 출력층(output layer) 가운데 위치한 층이 은닉층(hidden layer)이라고 불린다. 입력층과 출력층과는 달리 은닉층은 사람이 직접 관찰할 수 없다. 그렇기에 은닉층이라 불린다. 

 

 

퍼셉트론에서는 $x_1, x_2$를 입력으로 받아 $y$를 출력하였다. 하지만 실제로는 $b$라고 불리우는 편향(bias)도 존재하며 $b$를 포함한 퍼셉트론의 수식은 다음과 같이 정의된다. 

 

$ y = \begin{cases} 0 \ (b + w_1x_1 + w_2x_2 \le \theta) \\ \\ 1 \ (b + w_1x_2 + w_2x_2 > \theta ) \end{cases}$

 

위 수식을 조금 더 간결하게 표현하면 다음과 같다. 

 

$y = h(b + w_1x_1 + w_2x_2) $

 

$ h(x) = \begin{cases} 0 \ (x \le 0) \\ \\ 1 \ (x > \theta ) \end{cases}$

 

입력 신호의 총합이 $h(x)$라는 함수를 거쳐 출력된다. 딥러닝는 $h(x)$를 활성화 함수(activation function)이라고 부른다. $a = h(b + w_1x_1 + w_2x_2) $라고 하면, 활성화 함수는 $a$를 입력 받아 $y$를 출력하는 함수가 된다. 

 

 

각각의 노드들로 부터 입력받은 값을 합산해 $a$를 도출하고, 활섬화 함수인 $h()$를 거쳐 $y$를 출력하는 일련의 과정이 된다. 딥러닝에서 사용되는 활성화 함수에는 여러 종류가 존재하는데 대표적인 활성화 함수는 계단 함수(step function), 시그모이드 함수(sigmoid function), 렐루(Rectified Linear Unit; ReLU)가 존재한다.[코드] [참고자료]

 

계단 함수(Step function)

계단 함수는 입력 값이 0보다 크면 1을 출력하고, 그 외의 값은 1을 출력하는 간단한 함수이다. 

 

$ step(x) = \begin{cases} 0 \ (x \le 0) \\ \\ 1 \ (x > \theta ) \end{cases}$

 

 

시그모이드 함수(Sigmoid function)

시그모이드 함수는 딥러닝에서 자주 쓰이는 함수 중 하나이다.[코드]

 

\[ Sigmoid(x) = \frac{1}{1 + \exp(-x)} \]

 

 

 

계단 함수의 경우 값이 0 인근에서 왔다갔다할 경우 계속적으로 잘못 분류할 수 있는 경우가 존재한다. 갑자기 출력이 바뀌어버리기 때문이다. 하지만 시그모이드 함수는 계단 함수에 비해 상대적으로 매끄럽기 때문에 실제 분석을 진행할때에는 계단 함수보다 시그모이드 함수를 많이 사용한다. 

 

 

ReLU(Rectified Linear Unit)

ReLU는 렐루라고도 부른다. 예전에는 시그모이드 함수를 많이 사용했지만, 최근에는 시그모이드 함수보다 ReLU를 많이 사용한다. 나중에 다루겠지만 Gradient banishing 혹은 Gradient Exploding 문제로 인해 ReLU를 많이 사용한다.[코드] ReLU는 0을 넘으면 입력값 그대로를 출력하고, 0 이하일 경우 0을 출력하는 함수다. 

 

$ ReLU(x) = max(0, x) $

 

 

 

지금까지 활성화 함수에 대해서 다루어보았다. 지금까지 다룬 활성화 함수는 공통적인 부분이 존재한다. 바로 전부 비선형 함수(non-linear function)이라는 것이다. 만약 활성화 함수로 선형 함수를 사용하게 된다면 굳이 층을 여러겹 쌓을 이유가 없기 때문이다. $y(x) = h(h(h(x)))$라고 한다면, 이 계산 식은 $y(x) = c\ *\ c\ *\ c\ *\ x$와 동일하기 때문이다. 그렇기에 활성화 함수는 무조건 비선형 함수를 사용하여야 한다. [참고자료]

 

 

출력층

신경망은 분류와 회귀 문제에 모두 사용할 수 있다. 이 챕터에서는 분류 문제를 다룰 것이며 분류 문제를 다룰땐 출력층에 소프트맥스(softmax) 함수를 사용한다. 소프트맥스는 시그모이드와 유사한 형태를 띄며, 클래스의 수가 0 또는 1만 가질 경우 시그모이드와 일치한다. 수식은 다음과 같다. 

 

\[ y_k = \frac{\exp(a_k)}{ \sum_{i=1}^{n} \exp(a_i)} \]

 

소프트맥스는 $exp$ 즉, 지수함수를 사용한다. 지수함수의 경우 $x$의 값이 커지면 커질수록 기하급수적으로 값이 커진다. $e^{1000}$의 경우 $\infty$로 가버리기 때문이다. 그렇기에 우리는 다음과 같은 간단한 조작을 취할 수 있다. 

 

\[ y_k = \frac{\exp(a_k)}{ \sum_{i=1}^{n} \exp(a_i)}  = \frac{C \exp(a_k)}{C \sum_{i=1}^n \exp(a_i)}\]

\[ = \frac{ \exp(a_k + \log C)}{\sum_{i=1}^n \exp(a_i + \log C)} \]

\[ = \frac{\exp(a_k  + C^{\prime})}{\sum_{i=1}^n \exp(a_i + C^{\prime})} \]

 

위와 같이 상수 $C$를 더하거나 빼주어도 동일한 결과가 출력된다. 하지만 상수 $C$를 더하거나 빼줌으로써 출력값이 $\infty$로 가는 것을 막아준다. 일반적으로 입력 신호 중 최댓값을 상수 $C$로 이용한다.[코드]

 

 

지금까지 입력, 출력, 퍼셉트론, 활성화 함수 등 딥러닝의 기초가 되는 내용은 다 다루었다. 이 책에서는 이미지 처리에서 가장 많이 사용되는 MNIST 데이터를 기반으로 간단한 퍼셉트론에 대한 예제에 대한 코드는 여기를 참고하면 된다.