본문 바로가기
공부 정리/딥러닝

[딥러닝2]신경망의 순전파

by 블로그별명 2024. 1. 8.

저번 포스팅에서는 단층 퍼셉트론의 기본 개념과 한계에 대해 살펴보았고, 비선형 문제를 해결하기위해 다층 퍼셉트론이 필요함을 이해했습니다. 이번 페이지에서는 신경망의 순전파, 즉 주어진 입력에 대해 신경망의 최종적인 예측까지의 과정을 살펴보겠습니다.

신경망의 구현 

그림1

  • 신경망[각주:1]은 입력층, 은닉층, 출력층의 세 부분으로 구성됩니다. 각 층(Layer)은 뉴런(노드)으로 이루어져있으며, 뉴런은 다수의 신호를 입력으로 받아 정보를 처리하고 다음층의 뉴런으로 신호를 전달합니다.
    • 입력층
      신경망의 첫번째 층으로 일반적으로 0층으로 칭해집니다. 입력층의 뉴런수는 신경망으로 들어오는 입력 데이터의 특성(feature)수와 같은데 예를들어 28x28픽셀 크기의 이미지를 입력으로받는 신경망의 경우, 입력층에 784(28x28)개의 노드가 있으며, 각 노드에서 이미지 한 픽셀의 밝기값을 받을수있습니다.
    • 은닉층
      입력층과 출력층 사이에 위치하며, 신경망의 핵심적인 데이터 처리가 이루어지는곳입니다. 은닉층에서는 주로 고차원 데이터의 변환이 이루어지기때문에 이러한 학습과정을 직관적으로 이해하는데 어려움이 있을수있습니다.
    • 출력층
      신경망의 최종층으로, 여기서는 입력데이터에 대한 최증 결론이나 예측이 이루어집니다. 출력층의 노드수와 활성화 함수는 신경망으로 다루는 문제의 유형에 따라 달라집니다.

문제의 유형에 따른 출력층의 설계

신경망은 분류 [각주:2] 및 회귀[각주:3]문제를 해결하는데 사용될수있습니다. 다음은 문제의 유형에 따른 신경망의 출력층 형태입니다.

  • 회귀
    대부분의 회귀 모델은 하나의 값을 예측하므로, 출력층에는 보통 하나의 뉴런만 존재합니다. 그러나 여러값을 동시에 예측해야 할경우, 출력층에는 예측해야 할 값의 수만큼 뉴런이 존재합니다. 또한 회귀모델의 목적은 연속적인 값을 예측하는것이기 때문에, 일반적으로 출력층에서 별도의 활성화 함수를 사용하지않습니다. 다만 주가의 변동폭 예측처럼 출력값이 특정 범위 내에 있어야 할때는 활성화 함수를 사용하여 출력을 조절할수있습니다.
  • 이진분류
    이진분류는 두개의 클래스중 하나로 데이터를 분류하는것입니다. 예를들어 스팸메일 분류가 이진분류입니다. 이진분류 모델은 출력층에 보통 하나의 뉴런을 가지며, 활성화 함수로는 주로 시그모이드(sigmoid)함수가 사용됩니다. 시그모이드 함수는 출력값을 0에서 1사이로 제한하며, 이는 하나의 클래스에 대한 확률을 나타냅니다. 이때 비슷한 역할을 하는 계단함수대신 시그모이드 함수가 사용되는 이유중 하나는, 시그모이드 함수는 0과 1사이의 연속적인 값을 출력하기때문에 모델의 예측에 대한 확신도를 알수있어, 사용자에게 더 많은 정보를 제공한다는 점입니다.
  • 다중분류
    다중분류는 세개 이상의 클래스중 하나로 데이터를 분류하는것을 말합니다. 다중분류 모델의 출력층에는 클래스의 수 만큼의 뉴런이 존재하며, 활성화 함수로는 주로 소프트맥스함수가 사용됩니다. 소프트 맥스함수는 입력값으로 출력층에서 선형변환된 벡터를 받아 각 클래스에 대한 확률분포를 출력합니다.

다양한 활성화 함수

대표적인 활성화 함수인 시그모이드 함수, ReLU 함수 그리고 소프트맥스 함수에 대해 알아보고, 직접 코드로 구현해 보겠습니다.

 

시그모이드(sigmoid) 함수를 수식으로 표현하면 다음과 같습니다. \( h(x) = \frac{1}{1 + e^{-x}} \)  시그모이드 함수는 확실히 계단함수와 비슷하게 생겼습니다.

import numpy as np
import matplotlib.pyplot as plt

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def step_function(x):
    return np.where(x > 0, 1, 0)

x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
plt.plot(x, y)

y = step_function(x)
plt.plot(x, y, color = 'black', linestyle='--')

plt.show()

하지만, 계단함수와는 달리 연속적인 값을 출력하기 때문에, 미분이 가능하여, 기울기 계산에 효율적인 역전파 알고리즘을 적용할수있습니다. 그러나 시그모이드 함수는 입력값이 매우크거나 작을때, 아주 작은 미분값을 가지기때문에 기울기 소실 문제[각주:4]가 발생할 수 있습니다. 따라서 현재는 주로 이진분류 모델의 출력층에서만 사용되고 있습니다.

 

ReLU 함수

ReLU는 신경망에서 사용되는 ‘인기있는😎’ 활성화 함수입니다. 수식으로 표현하면 다음과 같습니다.

\( h(x) = \begin{cases} 
x &  (x > 0) \\
0 & (x \leq 0)
\end{cases} \)

ReLU는 다음과 같이 단순하게 생겼습니다.

import numpy as np
import matplotlib.pyplot as plt

def relu(x):
    return np.maximum(0, x)

x = np.arange(-5.0, 5.0, 0.1)
y = relu(x)
plt.plot(x, y)
plt.show()

이제 ReLU가 어째서 인기있는 활성화 함수인지 말해보겠습니다. 먼저 ReLU 함수의 미분 계산은 매우 단순합니다. 입력값이 0보다 크면 미분값은 1이고, 그외의 경우에는 0입니다. 따라서 ReLU는 다른 활성화 함수보다 역전파계산이 빠른 편입니다. 두번째로 입력값이 매우 크거나 작을때 미분값이 0에 가까워지는 시그모이드 함수와 달리, ReLU는 양수일때 미분값이 항상 1로 유지되므로, 기울기 소실 문제에 비교적 ‘덜’ 민감한 편입니다.

 

소프트맥스 함수

소프트맥스 함수를 수식으로 표현하면 다음과 같습니다. 수식에서 \( \exp(x) \)는 \( e^x \)를 뜻합니다.

\( y_k = \frac{\exp(z_k)}{\sum_{i=1}^{n} \exp(z_i)} \)

다만, 코드로 소프트 맥스 함수 구현시 약간의 문제점이 있는데요? 지수 함수가 입력값에 비해 매우큰 출력값을 생성한다는점입니다. 예를들어, \( e^{1000} \) 의 출력값은 너무 큰 나머지, 무한대를 뜻하는 inf를 출력하게 됩니다. 따라서 기존 소프트맥스 함수 수식을 다음과 같이 수정할 필요성이 있습니다.

\( y_k = \frac{\exp(z_k)}{\sum_{i=1}^{n} \exp(z_i)} = \frac{C\exp(z_k)}{C\sum_{i=1}^{n} \exp(z_i)} \)

\( = \frac{\exp(z_k+\log C)}{\sum_{i=1}^{n} \exp(z_i+\log C)} \)

\( = \frac{\exp(z_k+ C')}{\sum_{i=1}^{n} \exp(z_i+ C')} \)

 

여기서 상수 \( C' \)는 보통 \( -\max(z) \) 로 설정됩니다.

이 방법을 사용하여 소프트맥스의 함수의 결과에 영향을 주지않으면서도 큰 수에 의한 오버플로우를 방지할수있습니다.

def softmax(z):
    c = np.max(z)
    exp_z = np.exp(z - c)
    sum_exp_z = np.sum(exp_z)
    y = exp_z / sum_exp_z
    return y

 

 

행렬을 사용한 신경망의 계산

신경망의 계산은 행렬을 사용해 효율적으로 이루어집니다. 예를들어 아래와 같은 신경망 구조를 가정해보겠습니다.

그림1

이때, 3개의 입력 벡터에 대한 신경망의 계산을 수식으로 나타내면 다음과 같습니다.

\( \left[     \begin{array}{cc}         x_1 & x_2 \\         x_3 & x_4 \\         x_5 & x_6     \end{array} \right] \cdot \left[     \begin{array}{ccc}         w_1 & w_3 & w_5 \\         w_2 & w_4 & w_6     \end{array} \right] + \left[     \begin{array}{ccc}         b_1 & b_2 & b_3 \\         b_1 & b_2 & b_3 \\         b_1 & b_2 & b_3     \end{array} \right] \)

\( X \) 의 크기는 입력벡터의 수 \( \times \)  특성수, \( W \) 의 크기는 특성수 \( \times \)  1층의 뉴런 수 입니다. 이를 바탕으로 어떤 신경망이든 관계없이, 신경망의 최종 출력 행렬의 크기는 입력벡터의 수 \( \times \) 출력층의 뉴런 수 라는것을 알수있습니다.

 

이제 [그림1]신경망의 순전파 과정을 코드로 구현해보겠습니다.

  • 편향같은경우, 넘파이의 브로드캐스팅 기능을 이용하면 편향의 크기를 $m \times p$로 확장하지않아도 되서, 구현이 더 간단해집니다.
  • 활성화 함수로는 ReLU를 이용해보겠습니다.
  • 입력값과 편향 그리고 가중치는 모두 -0.5~0.5사이의 임의의 값을 부여하겠습니다.
import numpy as np

def relu(x):
    return np.maximum(0, x)

# 임의의 입력 데이터 X (3x2 행렬)
X = np.random.rand(3, 2) - 0.5

# 임의의 가중치 W (2x3 행렬)
W = np.random.rand(2, 3) - 0.5

# 임의의 편향 b (3차원 벡터)
b = np.random.rand(3) - 0.5

# 신경망 연산 수행
output = relu(np.dot(X, W) + b)

print(output)

 

간단한 신경망의 순전파를 구현해봤습니다 하지만, 사용된 파라미터의 값은 임의로 설정된것이므로, 의미있는 추론이라고 보기에는 어렵습니다. 다음 포스팅에서는 신경망의 학습과정 즉, 신경망이 스스로 적절한 파라미터값을 찾아내는 과정에 대해 자세히 살펴보겠습니다.

 

 

 

 


 

  1. 신경망이 특정데이터셋에 대해 학습을 완료한상태인경우 모델이라고 부르기도 합니다. [본문으로]
  2. 입력 데이터가 어떤클래스에 속할지 예측하는 문제. 예를들어 사진속 인물을 보고 성별을 예측하는문제는 분류문제라고 할수있습니다. [본문으로]
  3. 입력 데이터로부터 연속적인 수치를 예측하는 문제. 예를들어 사진속 인물을 보고 몸무게를 예측하는 문제는 회귀문제라고 할수있습니다. [본문으로]
  4. 기울기 소실 문제는 어떤 활성화 함수의 미분값이 매우 작을경우, 역전파 과정에서, 해당뉴런과 해당 뉴런과 앞쪽으로 연결된 뉴런들의 파라미터가 거의 업데이트 되지않는 문제를 말합니다. [본문으로]

'공부 정리 > 딥러닝' 카테고리의 다른 글

[딥러닝1]퍼셉트론  (0) 2023.12.26
Pooling 레이어의 이해  (0) 2023.02.21
패딩(padding) 사용하는 이유  (0) 2023.02.21
합성곱 연산(Convolution operation) 방법  (0) 2023.02.21
합성곱 신경망의 필요성  (0) 2023.02.21

댓글