4  퍼셉트론과 다층 퍼셉트론

학습 목표
  • 생물학적 뉴런과 인공 뉴런(퍼셉트론)의 대응 관계를 설명할 수 있다
  • 퍼셉트론의 구성요소(입력노드, 가중치, 편향, 합, 활성화 함수, 출력)를 이해한다
  • 주어진 가중치로 퍼셉트론의 출력을 직접 계산할 수 있다
  • 단일 퍼셉트론의 한계(XOR 문제)를 이해한다
  • 다층 퍼셉트론(MLP)이 비선형 문제를 해결하는 원리를 이해한다
  • 비선형 활성화 함수가 왜 핵심인지 설명할 수 있다
  • 활성화 함수의 종류(Sigmoid, Tanh, ReLU)와 특성을 비교할 수 있다
  • 인공신경망의 구조(입력층, 은닉층, 출력층)와 파라미터 개수를 계산할 수 있다

4.1 뇌에서 영감을 얻다

4.1.1 왜 뇌를 모방하려 했는가?

앞 장에서 우리는 모형이란 \(X\)\(y\)의 관계를 수학적으로 표현한 것이라고 배웠다. 그런데 인간의 뇌는 어떤 수학 공식도 없이, 사진 한 장만 보고도 “고양이”와 “개”를 구분하고, 처음 듣는 문장의 의미를 즉시 이해한다.

이렇게 복잡한 문제를 자연스럽게 푸는 뇌의 비밀은 무엇일까?

핵심 아이디어: 뇌의 뉴런(neuron) 하나하나는 매우 단순한 연산만 수행한다. 하지만 수백억 개의 뉴런이 연결(network)되면 놀라운 능력이 나타난다. 이 원리를 수학으로 옮긴 것이 인공신경망이다.

4.1.2 생물학적 뉴런의 구조

사람의 뇌는 약 860억 개의 뉴런으로 이루어져 있다. 각 뉴런은 수천 개의 다른 뉴런과 연결되어 전기적 신호를 주고받는다.

생물학적 뉴런의 구조 (Blausen Medical, CC BY 3.0)

뉴런의 신호 전달 과정:

  1. 수상돌기(Dendrite)가 다른 뉴런으로부터 신호를 수신
  2. 세포체(Cell body)에서 신호를 합산
  3. 합산된 신호가 임계값을 넘으면 활성화
  4. 축삭(Axon)을 통해 다음 뉴런으로 신호를 전달
  5. 시냅스(Synapse)에서 연결 강도에 따라 신호의 세기가 조절됨

이 과정이 수백억 번 동시에 일어나면서 인간의 사고가 이루어진다.

4.1.3 생물학적 뉴런 → 인공 뉴런

이 신호 전달 과정을 수학적으로 단순화하면 인공 뉴런이 된다.

생물학적 뉴런 수상돌기 (신호 수신) 세포체 (신호 합산) 축삭 (신호 전달) 시냅스 수학적 모방 인공 뉴런 (퍼셉트론) x₁ x₂ x₃ 입력 (수상돌기) w₁ w₂ w₃ 가중치 (시냅스) Σ 합 (세포체) g(z) 활성화 ŷ 출력 (축삭)
인공신경망 (Artificial Neural Network)

생물학적 뉴런의 전기적 신호처리를 수학적으로 모방한 모형.

생물학적 뉴런 역할 인공 뉴런
수상돌기 (Dendrite) 신호 수신 입력 노드 (\(x_1, x_2, \ldots\))
시냅스 강도 (Synapse) 연결 세기 조절 가중치 (\(w_1, w_2, \ldots\))
세포체 (Soma) 신호 합산 가중합 (\(\Sigma\))
축삭 (Axon) 활성화 후 전달 활성화 함수 → 출력 (\(\hat{y}\))

뉴런 하나의 연산은 단순하지만, 수천~수백만 개를 연결하면 이미지 인식, 자연어 처리 등 복잡한 문제를 풀 수 있다.


4.2 퍼셉트론 (Perceptron)

4.2.1 정의

앞에서 본 인공 뉴런 하나를 퍼셉트론(Perceptron)이라고 부른다.

퍼셉트론 (Perceptron)

딥러닝을 구성하는 기본요소. 입력값을 받아 출력값으로 변환하는 단위. 아무리 복잡한 딥러닝 모델(GPT, 이미지 분류기 등)도 결국 퍼셉트론의 조합으로 이루어진다.

4.2.2 퍼셉트론의 5가지 구성요소

퍼셉트론 내부에서 데이터가 왼쪽에서 오른쪽으로 흐르며 처리되는 과정을 단계별로 따라가 보자.

입력 노드 가중치 편향 활성화 함수 1 x₁ x₂ 데이터의 특성(feature) w₀ w₁ w₂ Σ z = w₀ + w₁x₁ + w₂x₂ z g(z) 비선형 변환 ŷ 예측값 최종 출력 데이터 흐름 방향
순서 구성요소 뉴런 대응 설명
입력 노드 (\(x_i\)) 수상돌기 데이터의 특성(feature) 하나씩에 대응
가중치 (\(w_i\)) 시냅스 강도 각 입력이 얼마나 중요한지를 나타내는 계수
편향 (\(w_0\)) 기저 활성 항상 1의 값을 갖는 기본 노드, 기준점 역할
(\(z\)) 세포체 입력과 가중치의 선형 결합: \(z = w_0 + \sum w_i x_i\)
활성화 함수 \(g(z)\) 축삭 발화 합을 변환하여 최종 출력을 생성

4.2.3 수학적 표현

퍼셉트론의 출력은 두 단계로 계산된다.

1단계: 가중합 (Weighted Sum)

\[z = w_0 + \sum_{i=1}^{m} w_i x_i = w_0 + w_1 x_1 + w_2 x_2 + \cdots + w_m x_m\]

  • \(x_1, \ldots, x_m\): 입력 노드
  • \(w_1, \ldots, w_m\): 가중치
  • \(w_0\): 편향 (bias) — 입력값이 항상 1인 노드에 곱해지는 가중치

2단계: 활성화 함수 적용

\[\hat{y} = g(z) = g\left(w_0 + \sum_{i=1}^{m} w_i x_i\right)\]

  • \(g(\cdot)\): 활성화 함수
  • \(\hat{y}\): 최종 출력값

4.3 퍼셉트론의 수치 계산

4.3.1 예시: 회귀 문제 — 항등 함수

다음과 같은 퍼셉트론이 주어졌다고 하자.

  • 입력: \(x_1, x_2\)
  • 가중치: \(w_0 = -0.3\), \(w_1 = 0.5\), \(w_2 = 0.5\)
  • 활성화 함수: \(g(z) = z\) (항등 함수, 회귀문제용)
코드
import pandas as pd

rows = []
for x1, x2 in [(0,0), (1,0), (0,1), (1,1)]:
    z = -0.3 + 0.5*x1 + 0.5*x2
    y_hat = z  # 항등 함수
    rows.append({
        '$x_1$': x1, '$x_2$': x2,
        '$z = -0.3 + 0.5x_1 + 0.5x_2$': f'{z:.1f}',
        '$\\hat{{y}} = g(z) = z$': f'{y_hat:.1f}',
    })

pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 4.1: 퍼셉트론 회귀 출력 — g(z) = z
\(x_1\) \(x_2\) \(z = -0.3 + 0.5x_1 + 0.5x_2\) \(\\hat{{y}} = g(z) = z\)
0 0 -0.3 -0.3
1 0 0.2 0.2
0 1 0.2 0.2
1 1 0.7 0.7

4.3.2 분류 문제 — 계단 함수

같은 가중치에서 활성화 함수를 계단 함수(step function)로 바꾸면, 분류문제를 표현할 수 있다.

\[g(z) = \begin{cases} 1 & \text{if } z \geq 0 \\ 0 & \text{if } z < 0 \end{cases}\]

코드
import pandas as pd

rows = []
for x1, x2 in [(0,0), (1,0), (0,1), (1,1)]:
    z = -0.3 + 0.5*x1 + 0.5*x2
    y_hat = 1 if z >= 0 else 0
    rows.append({
        '$x_1$': x1, '$x_2$': x2,
        '$z$': f'{z:.1f}',
        '$g(z)$': y_hat,
        '판정': '클래스 1' if y_hat == 1 else '클래스 0',
    })

pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 4.2: 퍼셉트론 분류 출력 — 계단 함수
\(x_1\) \(x_2\) \(z\) \(g(z)\) 판정
0 0 -0.3 0 클래스 0
1 0 0.2 1 클래스 1
0 1 0.2 1 클래스 1
1 1 0.7 1 클래스 1

이 퍼셉트론의 출력 패턴 \((0, 1, 1, 1)\)OR 게이트와 동일하다!


4.4 정형 데이터 한 줄을 퍼셉트론에 넣어보기

지금까지 입력은 \(0\)\(1\)뿐이었다. 하지만 실제 데이터는 그렇지 않다. Ch01의 정형 데이터 한 을 그대로 퍼셉트론에 넣어보자.

먼저 알아둘 것 — Ch01의 회귀모형이 곧 퍼셉트론 하나다

Ch01에서 우리는 이런 모형을 세웠다.

\[y = w_0 + w_1 x_1 + w_2 x_2 + w_3 x_3\]

그리고 이 장에서 퍼셉트론의 가중합은 이렇게 정의했다.

\[z = w_0 + w_1 x_1 + w_2 x_2 + w_3 x_3\]

완전히 같은 식이다. 활성화 함수가 항등함수 \(g(z) = z\)인 퍼셉트론 하나는 Ch01의 다중회귀모형과 정확히 같은 모형이다.

새로운 것은 두 가지뿐이다 — 활성화 함수를 비선형으로 바꿀 수 있다는 것, 그리고 이것을 여러 개 쌓을 수 있다는 것. 딥러닝은 여기서 시작한다.

4.4.1 ✍️ 손으로 따라 계산하기

어떤 고객의 이탈 위험 점수를 예측하는 퍼셉트론이 있다. 입력은 정형 데이터의 세 열이다.

변수 이 고객의 값
\(x_1\) 가입 개월 수 (표준화된 값) \(-1.2\)
\(x_2\) 월 사용액 (표준화된 값) \(0.5\)
\(x_3\) 최근 3개월 문의 횟수 \(4\)

학습된 파라미터는 다음과 같다.

\[w_0 = 0.3, \quad w_1 = -0.8, \quad w_2 = -0.5, \quad w_3 = 0.6\]

활성화 함수는 Sigmoid \(\sigma(z) = \dfrac{1}{1+e^{-z}}\) 이다 (출력을 이탈 확률로 읽기 위해).

단계 1 — 각 항을 하나씩 곱한다. 한꺼번에 하지 말고 한 줄씩 쓴다.

\[ \begin{aligned} w_1 x_1 &= (-0.8) \times (-1.2) = 0.96 \\ w_2 x_2 &= (-0.5) \times (0.5) = -0.25 \\ w_3 x_3 &= (0.6) \times (4) = 2.4 \end{aligned} \]

단계 2 — 편향과 함께 모두 더한다.

\[z = \underbrace{0.3}_{w_0} + 0.96 - 0.25 + 2.4 = 3.41\]

단계 3 — 활성화 함수를 통과시킨다.

\[\hat{y} = \sigma(3.41) = \frac{1}{1 + e^{-3.41}} = \frac{1}{1 + 0.0331} = 0.968\]

해석: 이 고객의 이탈 확률은 약 96.8%다. \(x_3\)(문의 횟수 4회)이 \(0.6 \times 4 = 2.4\)로 가중합을 크게 끌어올린 것이 결정적이었다 — 가중치가 클수록, 입력값이 클수록 그 항의 영향이 크다.

코드
import pandas as pd
import numpy as np

w = [0.3, -0.8, -0.5, 0.6]
x = [1.0, -1.2, 0.5, 4.0]      # x[0] = 1 (편향용)
names = ['편향 $w_0$', '$w_1 x_1$ (가입 개월)', '$w_2 x_2$ (월 사용액)', '$w_3 x_3$ (문의 횟수)']

rows = []
for nm, wi, xi in zip(names, w, x):
    rows.append({'항': nm, '$w_i$': wi, '$x_i$': xi, '기여 $w_i x_i$': round(wi * xi, 3)})

z = sum(wi * xi for wi, xi in zip(w, x))
rows.append({'항': '<b>합 $z$</b>', '$w_i$': '', '$x_i$': '', '기여 $w_i x_i$': f'<b>{round(z, 3)}</b>'})
rows.append({'항': '<b>$\\hat{y} = \\sigma(z)$</b>', '$w_i$': '', '$x_i$': '',
             '기여 $w_i x_i$': f'<b>{round(1/(1+np.exp(-z)), 3)}</b>'})

pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 4.3: 정형 데이터 한 행의 퍼셉트론 순전파 — 항별 기여도
\(w_i\) \(x_i\) 기여 \(w_i x_i\)
편향 \(w_0\) 0.3 1.0 0.3
\(w_1 x_1\) (가입 개월) -0.8 -1.2 0.96
\(w_2 x_2\) (월 사용액) -0.5 0.5 -0.25
\(w_3 x_3\) (문의 횟수) 0.6 4.0 2.4
\(z\) 3.41
\(\\hat{y} = \\sigma(z)\) 0.968

같은 퍼셉트론에 \((x_1, x_2, x_3) = (0.4,\ 1.5,\ 1)\)인 고객을 넣으면 \(z\)\(\hat{y}\)는 얼마인가?

정답을 보기 전에 반드시 손으로 먼저 계산하라.

정답 펼치기

\(w_1 x_1 = (-0.8)(0.4) = -0.32\)

\(w_2 x_2 = (-0.5)(1.5) = -0.75\)

\(w_3 x_3 = (0.6)(1) = 0.6\)

\(z = 0.3 - 0.32 - 0.75 + 0.6 = -0.17\)

\(\hat{y} = \sigma(-0.17) = \dfrac{1}{1 + e^{0.17}} = \dfrac{1}{1 + 1.1853} = 0.458\)

→ 이탈 확률 약 45.8%. 앞 고객(96.8%)과 달리 위험이 낮다. 문의 횟수가 적고 사용액이 많은 것이 \(z\)를 끌어내렸다.

연습을 더 하려면: 도장 2주차의 유형 A·E가 이 계산이다. 학번을 넣으면 본인만의 문제가 무한히 나온다.


인터랙티브 — 퍼셉트론의 가중치를 조절하며 출력을 확인해 보세요

\(w_0\) (편향), \(w_1\), \(w_2\)를 조절하면 퍼셉트론의 출력이 어떻게 변하는지 관찰하세요. 계단 함수 활성화를 사용하면, 가중치에 따라 AND, OR 등 다양한 논리 게이트를 표현할 수 있습니다.

시도해 보세요: \(w_0=-0.7, w_1=0.5, w_2=0.5\)로 설정하면 AND 게이트가 됩니다.


4.5 단일 퍼셉트론의 한계

위 인터랙티브에서 확인했듯이, 단일 퍼셉트론은 \(z = w_0 + w_1 x_1 + w_2 x_2 = 0\)이라는 직선 하나로 두 클래스를 나누는 결정 경계(decision boundary)를 만든다.

4.5.1 OR 게이트 — 단일 퍼셉트론으로 가능

\(w_0 = -0.3, w_1 = 0.5, w_2 = 0.5\), 계단 함수를 사용하면:

코드
import pandas as pd

rows = []
for x1, x2 in [(0,0), (1,0), (0,1), (1,1)]:
    z = -0.3 + 0.5*x1 + 0.5*x2
    y = 1 if z >= 0 else 0
    target = 1 if (x1 or x2) else 0
    rows.append({
        '$x_1$': x1, '$x_2$': x2,
        '$z$': f'{z:.1f}',
        '$\\hat{{y}}$': y,
        'OR 정답': target,
        '일치': '$$\\checkmark$$' if y == target else '$$\\times$$',
    })

pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 4.4: OR 게이트: 단일 퍼셉트론으로 구현
\(x_1\) \(x_2\) \(z\) \(\\hat{{y}}\) OR 정답 일치
0 0 -0.3 0 0 \[\\checkmark\]
1 0 0.2 1 1 \[\\checkmark\]
0 1 0.2 1 1 \[\\checkmark\]
1 1 0.7 1 1 \[\\checkmark\]

단일 퍼셉트론으로 OR 게이트를 완벽하게 표현할 수 있다. 이는 OR 데이터가 직선 하나로 두 클래스를 분리할 수 있기 때문이다.

4.5.2 XOR 게이트 — 단일 퍼셉트론으로 불가능

XOR 문제

\(x_1\)\(x_2\)다를 때 1, 같을 때 0을 출력하는 문제.

\(x_1\) \(x_2\) XOR
0 0 0
1 0 1
0 1 1
1 1 0

XOR 데이터를 직선 하나로 분리할 수 있는가?

결론: 같은 색(클래스)의 점을 직선 하나로 분리할 수 없다. 이것이 단일 퍼셉트론의 근본적 한계이다.


4.6 다층 퍼셉트론 (Multi-Layer Perceptron)

4.6.1 해결책: 퍼셉트론을 여러 개 조합

단일 퍼셉트론의 한계를 극복하려면, 퍼셉트론을 여러 층으로 쌓는다.

다층 퍼셉트론 (MLP, Multi-Layer Perceptron)

2개 이상의 퍼셉트론을 계층적으로 연결한 구조. 층은 역할에 따라 세 종류로 나뉜다.

  • 입력층(Input Layer): 데이터가 들어오는 첫 번째 층
  • 은닉층(Hidden Layer): 입력층과 출력층 사이에서 데이터를 변환하는 중간 층. 외부에서 직접 관측할 수 없어 “은닉”이라 부른다
  • 출력층(Output Layer): 최종 예측값을 내보내는 마지막 층

첫 번째 층의 출력이 다음 층의 입력이 되며, 각 층에서 비선형 활성화를 적용하면 전체 네트워크는 비선형 함수를 표현할 수 있다.

4.6.2 XOR을 2개의 퍼셉트론으로 풀기

다음과 같이 은닉층에 2개 노드, 출력층에 1개 노드를 배치하면 XOR을 풀 수 있다.

입력층 은닉층 출력층 x₁ x₂ s₁ (OR) s₂ (NAND) ŷ (AND) 0.5 0.5 −0.5 −0.5 0.5 0.5 b=−0.3 b=0.7 b=−0.7

은닉층 (Hidden Layer)

  • \(s_1\): \(w_0^{(1)}=-0.3,\ w_1^{(1)}=0.5,\ w_2^{(1)}=0.5\) → OR 게이트 역할
  • \(s_2\): \(w_0^{(2)}=0.7,\ w_1^{(2)}=-0.5,\ w_2^{(2)}=-0.5\) → NAND 게이트 역할

출력층 (Output Layer)

  • \(\hat{y}\): \(w_0^{(3)}=-0.7,\ w_1^{(3)}=0.5,\ w_2^{(3)}=0.5\) → AND 게이트 역할
코드
import pandas as pd

rows = []
for x1, x2 in [(0,0), (1,0), (0,1), (1,1)]:
    # Hidden layer
    z1 = -0.3 + 0.5*x1 + 0.5*x2   # OR
    s1 = 1 if z1 >= 0 else 0

    z2 = 0.7 + (-0.5)*x1 + (-0.5)*x2   # NAND
    s2 = 1 if z2 >= 0 else 0

    # Output layer
    z3 = -0.7 + 0.5*s1 + 0.5*s2   # AND
    y_hat = 1 if z3 >= 0 else 0

    xor_target = x1 ^ x2

    rows.append({
        '$x_1$': x1, '$x_2$': x2,
        '$z_1$': f'{z1:.1f}', '$s_1$ (OR)': s1,
        '$z_2$': f'{z2:.1f}', '$s_2$ (NAND)': s2,
        '$z_3$': f'{z3:.1f}', '$\\hat{{y}}$ (AND)': y_hat,
        'XOR 정답': xor_target,
        '일치': '$$\\checkmark$$' if y_hat == xor_target else '$$\\times$$',
    })

pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 4.5: 다층 퍼셉트론으로 XOR 문제 풀기 — 단계별 계산
\(x_1\) \(x_2\) \(z_1\) \(s_1\) (OR) \(z_2\) \(s_2\) (NAND) \(z_3\) \(\\hat{{y}}\) (AND) XOR 정답 일치
0 0 -0.3 0 0.7 1 -0.2 0 0 \[\\checkmark\]
1 0 0.2 1 0.2 1 0.3 1 1 \[\\checkmark\]
0 1 0.2 1 0.2 1 0.3 1 1 \[\\checkmark\]
1 1 0.7 1 -0.3 0 -0.2 0 0 \[\\checkmark\]

핵심 통찰: XOR = (OR) AND (NAND). 단일 퍼셉트론으로 불가능했던 문제를, 퍼셉트론 3개의 조합으로 해결하였다.


인터랙티브 — 다층 퍼셉트론의 XOR 계산을 단계별로 확인하세요

입력값 \((x_1, x_2)\)를 선택하면, 은닉층과 출력층의 계산 과정을 추적할 수 있습니다.


4.7 왜 비선형 활성화가 핵심인가

4.7.1 선형만 쌓으면 여전히 선형

XOR을 다층 퍼셉트론으로 풀 수 있었던 핵심 이유는 무엇인가?

만약 은닉층에서 활성화 함수 없이(또는 항등 함수 \(g(z)=z\)만 사용하여) 가중합만 반복한다면:

\[\hat{y} = W^{(2)} \cdot (W^{(1)} \cdot X) = (W^{(2)} W^{(1)}) \cdot X = W' \cdot X\]

결국 하나의 선형 변환 \(W'\)로 축소된다. 층을 아무리 깊게 쌓아도 직선 경계밖에 못 만든다.

4.7.2 비선형 활성화 → 비선형 경계

각 층의 출력에 비선형 활성화 함수를 적용하면 상황이 달라진다.

  • 은닉층의 각 노드가 입력 공간을 접고(fold), 휘어(bend) 새로운 표현을 만든다
  • 이 표현들이 조합되면서 곡선, 원, 임의의 복잡한 경계를 만들 수 있다
Universal Approximation Theorem

충분한 수의 은닉 노드와 비선형 활성화 함수를 가진 다층 퍼셉트론은 임의의 연속 함수를 원하는 정밀도로 근사할 수 있다.

  • 이론상으로 컴퓨터가 수행하는 처리도 모두 표현 가능
  • 딥러닝은 이 다층 퍼셉트론을 활용하여 사진 분류, 음성 인식, 자연어 처리 등을 수행

정리: 단일 퍼셉트론 = 직선 경계 → 비선형 활성화를 가진 다층 퍼셉트론 = 임의로 복잡한 경계. 비선형 활성화 함수는 딥러닝의 표현력을 결정하는 핵심 요소이다.


4.8 활성화 함수 (Activation Function)

그렇다면 실제로 어떤 비선형 활성화 함수가 사용되는가?

4.8.1 주요 활성화 함수

함수 수식 출력 범위 특징
Sigmoid \(\sigma(z) = \frac{1}{1+e^{-z}}\) \((0, 1)\) 확률 해석 가능
Tanh \(\tanh(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}}\) \((-1, 1)\) 0 중심, Sigmoid보다 빠른 수렴
ReLU \(\max(0, z)\) \([0, \infty)\) 계산 효율적, 현재 가장 많이 사용

4.8.2 수치 예시: 같은 입력에 대한 활성화 함수별 출력

코드
import pandas as pd
import numpy as np

zs = [-3.0, -1.0, 0.0, 0.5, 1.0, 3.0]
rows = []
for z in zs:
    sig = 1 / (1 + np.exp(-z))
    tanh = np.tanh(z)
    relu = max(0, z)
    rows.append({
        '$z$': z,
        'Sigmoid': f'{sig:.4f}',
        'Tanh': f'{tanh:.4f}',
        'ReLU': f'{relu:.1f}',
    })

pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 4.6: z값에 따른 활성화 함수 출력 비교
\(z\) Sigmoid Tanh ReLU
-3.0 0.0474 -0.9951 0.0
-1.0 0.2689 -0.7616 0.0
0.0 0.5000 0.0000 0.0
0.5 0.6225 0.4621 0.5
1.0 0.7311 0.7616 1.0
3.0 0.9526 0.9951 3.0

인터랙티브 — 활성화 함수의 형태를 비교해 보세요

활성화 함수를 선택하면 \(g(z)\)와 그 도함수 \(g'(z)\)의 그래프를 확인할 수 있습니다.

도함수를 함께 그려둔 이유는 다음 장에서 드러납니다 — 학습은 기울기를 따라 일어나므로, 기울기가 0에 가까운 구간(Sigmoid의 양 끝)에서는 학습이 거의 멈춥니다. ReLU가 현재 가장 많이 쓰이는 이유가 여기에 있습니다.


4.9 인공신경망의 구조

4.9.1 일반적인 신경망 구조

앞서 MLP에서 입력층·은닉층·출력층의 개념을 도입했다. 이를 일반화하면 인공신경망(Neural Network)이 된다.

입력층 은닉층 1 은닉층 2 출력층 x₁ x₂ x₃ ŷ₁ ŷ₂ 깊이 (depth) = 2 → “딥”러닝

각 층의 역할을 구체적으로 정리하면 다음과 같다.

역할 노드 수 결정
입력층 (Input Layer) 데이터의 특성(feature)을 받아들이는 층 특성 수와 동일
은닉층 (Hidden Layer) 데이터의 내부 표현(representation)을 학습하는 중간 층 설계자가 직접 결정
출력층 (Output Layer) 최종 예측값을 생성하는 층 문제 유형에 따라 결정

출력층의 노드 수는 문제 유형에 따라 달라진다.

  • 회귀: 1개 출력 노드
  • 이진 분류: 1개 출력 노드 (Sigmoid)
  • 다중 분류 (\(K\)개 클래스): \(K\)개 출력 노드 (Softmax)

4.9.2 인공신경망의 표현

구성 퍼셉트론 다중 퍼셉트론 딥 인공신경망
은닉층 수 0 1 2 이상
표현력 선형 비선형 매우 복잡한 비선형
딥 인공신경망 (Deep Neural Network)

입력층과 출력층 사이에 여러 개의 은닉층으로 구성된 인공신경망. 은닉층의 개수가 커질수록 깊이(depth)가 깊다고 표현한다. “딥러닝”이라는 이름의 유래.


4.10 파라미터 개수 계산

4.10.1 왜 파라미터 개수가 중요한가?

인공신경망의 파라미터(가중치 + 편향)의 총 개수는 모형의 복잡도를 나타낸다.

4.10.2 계산 규칙

\(l\)번째 층의 노드 수를 \(n_l\)이라 하면, \(l-1\)번째 층에서 \(l\)번째 층으로 연결되는 파라미터 수는:

\[\text{파라미터 수} = n_{l-1} \times n_l + n_l\]

  • \(n_{l-1} \times n_l\): 가중치 수 (모든 입력-출력 쌍)
  • \(n_l\): 편향 수 (출력 노드 하나당 하나)

4.10.3 수치 예시

입력 3개 → 은닉 4개 → 출력 1개인 신경망의 파라미터 수:

코드
import pandas as pd

layers = [
    ('입력층 → 은닉층', 3, 4),
    ('은닉층 → 출력층', 4, 1),
]

rows = []
total = 0
for name, n_in, n_out in layers:
    w = n_in * n_out
    b = n_out
    total += w + b
    rows.append({
        '연결': name,
        '입력 노드': n_in,
        '출력 노드': n_out,
        '가중치 수': f'${n_in} \\times {n_out} = {w}$',
        '편향 수': n_out,
        '소계': w + b,
    })

rows.append({
    '연결': '**합계**',
    '입력 노드': '', '출력 노드': '',
    '가중치 수': '', '편향 수': '',
    '소계': f'**{total}**',
})

pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 4.7: 인공신경망 파라미터 개수 계산
연결 입력 노드 출력 노드 가중치 수 편향 수 소계
입력층 → 은닉층 3 4 \(3 \\times 4 = 12\) 4 16
은닉층 → 출력층 4 1 \(4 \\times 1 = 4\) 1 5
합계 21

인터랙티브 — 신경망 구조를 바꾸며 파라미터 수를 확인하세요

입력, 은닉, 출력 노드 수를 변경하면 파라미터 수가 어떻게 변하는지 확인할 수 있습니다.


4.11 핵심 요약

개념 핵심 내용
퍼셉트론 입력 → 가중합 → 활성화 함수 → 출력의 기본 단위
가중합 \(z = w_0 + w_1 x_1 + \cdots + w_m x_m\)
단일 퍼셉트론 한계 직선 경계만 표현 가능 → XOR 불가
다층 퍼셉트론 퍼셉트론을 층으로 쌓아 비선형 문제 해결
비선형 활성화의 역할 선형만 쌓으면 여전히 선형 → 비선형 활성화가 표현력의 핵심
Sigmoid / Tanh / ReLU 출력 범위와 계산 특성이 다른 대표적 활성화 함수
인공신경망 구조 입력층 + 은닉층(1개 이상) + 출력층
딥 인공신경망 은닉층이 2개 이상인 신경망 → “딥러닝”
파라미터 수 \((n_{l-1} \times n_l + n_l)\)의 합