본문 바로가기
  • 책상 밖 세상을 경험할 수 있는 Playground를 제공하고, 수동적 학습에서 창조의 삶으로의 전환을 위한 새로운 라이프 스타일을 제시합니다.
Miscellaneous

[2025-1] 박경태 - 밑바닥부터 시작하는 딥러닝 리뷰, (CH 5.5) 활성화 함수 계층 구현하기

by corqjffp010 2025. 3. 26.

5.5 활성화 함수 계층 구현하기

신경망에서 각 계층(layer)의 출력값에 비선형성을 부여해주는 것이 바로 활성화 함수다. 이 장에서는 대표적인 활성화 함수인 ReLUSigmoid를 예로 들어, 그 동작 원리와 수식을 이해하고, 실제 코드로 어떻게 구현할 수 있는지 알아본다. 특히 역전파(backward) 과정에서의 계산 흐름까지 다루며, 신경망 학습의 핵심 개념을 직접 구현해볼 것이다.


5.5.1 ReLU 계층

🔹 ReLU 함수 정의 및 미분

ReLU(Rectified Linear Unit) 함수는 다음과 같이 정의된다:

\[
y = \begin{cases} 
x & \text{if } x > 0 \\
0 & \text{if } x \leq 0 
\end{cases}
\]
이는 입력값이 0보다 크면 그대로 출력하고, 작거나 같으면 0으로 바꾸는 매우 간단한 함수이다.
미분 값은 다음과 같다:
\[
\frac{\partial y}{\partial x} = 
\begin{cases} 
1 & \text{if } x > 0 \\
0 & \text{if } x \leq 0 
\end{cases}
\]

🔹 순전파/역전파 계산 흐름도

  • 순전파 시: 입력값이 0보다 크면 그대로 출력, 작거나 같으면 0 출력.
  • 역전파 시: 입력값이 0보다 크면 기울기(gradient)를 그대로 흘려보냄, 그렇지 않으면 0.

🔹 파이썬 구현

class Relu:
    def __init__(self):
        self.mask = None

    def forward(self, x):
        self.mask = (x <= 0)
        out = x.copy()
        out[self.mask] = 0
        return out

    def backward(self, dout):
        dout[self.mask] = 0
        dx = dout
        return dx

🔹 마스크(mask)의 개념

mask는 입력값이 0 이하인 위치를 기억하는 True/False 배열로, 역전파 계산 시 0을 흘려보낼 위치를 지정하는 역할을 한다.

예시:

x = np.array([[1.0, -0.5], [-2.0, 3.0]])
mask = (x <= 0)
# 결과: [[False True], [True False]]

이 mask를 이용해 역전파 때 해당 위치의 기울기를 0으로 만든다.


5.5.2 Sigmoid 계층

🔹 Sigmoid 함수 정의

Sigmoid 함수는 다음과 같은 수식으로 정의된다:

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

이 함수는 입력값을 0과 1 사이로 압축하는 S자 형태의 곡선을 만든다.

🔹 순전파 계산 그래프

Sigmoid 함수는 계산 그래프상 다음과 같은 과정을 거친다:

  1. -x를 계산
  2. exp(-x)를 계산
  3. 1 + exp(-x)를 더함
  4. 1 / (1 + exp(-x)) 계산 → 최종 결과 y

🔹 역전파 계산 흐름도 (4단계)

1단계:
\[
\frac{\partial y}{\partial x} = -\frac{1}{x^2} = -y^2
\]
2단계:  
덧셈 노드는 상류 값을 그대로 하류로 전달한다.
3단계:  
\[
\exp \text{ 노드는 미분 시 } \frac{\partial y}{\partial x} = \exp(x)
\]
4단계:  
곱셈 노드는 순전파에서 곱했던 값을 역전파 시 서로 바꿔 곱한다.
이를 모두 조합하면, 최종적으로 Sigmoid 함수의 미분 결과는 다음과 같이 정리된다:
\[
\frac{\partial y}{\partial x} = y(1 - y)
\]

🔹 간소화된 계산 그래프

계산 그래프의 중간 과정을 생략하면 아래와 같이 간단한 노드로 표현할 수 있다:

\[
\text{입력: } x \rightarrow \text{sigmoid 노드} \rightarrow y \quad \text{역전파: } \frac{\partial L}{\partial y} \cdot y(1 - y)
\]

🔹 파이썬 구현

class Sigmoid:
    def __init__(self):
        self.out = None

    def forward(self, x):
        out = 1 / (1 + np.exp(-x))
        self.out = out
        return out

    def backward(self, dout):
        dx = dout * (1.0 - self.out) * self.out
        return dx

self.out에 순전파의 출력 값을 저장해두고, 역전파 시 해당 값을 활용해 기울기를 계산한다.


❓ 퀴즈

다음 중 Sigmoid 함수의 역전파 계산식으로 올바른 것은?

\begin{align*}
\text{(A)} \quad & \frac{\partial y}{\partial x} = x(1 - x) \\
\text{(B)} \quad & \frac{\partial y}{\partial x} = y(1 - y) \\
\text{(C)} \quad & \frac{\partial y}{\partial x} = y^2 \\
\text{(D)} \quad & \frac{\partial y}{\partial x} = 1 - y^2
\end{align*}