5  딥러닝의 학습

학습 목표
  • 딥러닝에서 학습(Learning)이 무엇인지 정의할 수 있다
  • 손실 함수(Loss Function)의 역할을 이해하고, MSE와 교차 엔트로피를 직접 계산할 수 있다
  • Softmax 함수의 역할과 계산 과정을 이해한다
  • 경사하강법(Gradient Descent)의 원리를 수학적으로 설명할 수 있다
  • 미분과 편미분이 “조금 바꾸면 얼마나 변하는가”임을 이해하고, 간단한 도함수를 직접 구할 수 있다
  • 순전파 → 손실 → 역전파 → 갱신으로 이어지는 학습 루프의 전체 흐름을 설명할 수 있다
이 수업의 계산 약속

이 장부터 계산기가 필요하다. 답이 갈리지 않도록 두 가지를 미리 못 박아 둔다.

  • \(\log\) 는 항상 자연로그 \(\ln\) 이다 (밑 \(= e \approx 2.71828\)). 상용로그(밑 10)가 아니다. 교재·도장·시험 전부 동일하다.
  • 별도 지시가 없으면 소수 넷째 자리에서 반올림하여 셋째 자리까지 쓴다.

5.1 딥러닝에서 “학습”이란?

5.1.1 학습의 정의

학습 (Learning)

주어진 데이터로부터 손실 함수(Loss Function)를 최소화하는 파라미터(가중치, 편향)를 찾아가는 과정.

\[\hat{\boldsymbol{\theta}} = \arg\min_{\boldsymbol{\theta}} \mathcal{L}(\boldsymbol{\theta})\]

  • \(\boldsymbol{\theta}\): 모든 가중치와 편향의 집합
  • \(\mathcal{L}\): 손실 함수 — 예측값과 실제값의 차이를 측정

학습 과정은 크게 3단계로 이루어진다.

단계 내용 핵심 질문
1 손실 함수 정의 예측이 얼마나 틀렸는가?
2 그래디언트 계산 어느 방향으로 파라미터를 바꿔야 하는가?
3 파라미터 갱신 얼마나 바꿀 것인가?
① 순전파 X → 모형 → ŷ (예측값 계산) ② 손실 계산 L(y, ŷ) (오차 측정) ③ 역전파 ∂L/∂θ 계산 (그래디언트) ④ 파라미터 갱신 θ ← θ − η·∇L (학습률 적용) 반복 (Epoch) 딥러닝 학습 루프

5.2 손실 함수 (Loss Function)

5.2.1 왜 손실 함수가 필요한가?

모형의 예측값 \(\hat{y}\)와 실제값 \(y\)가 얼마나 다른지를 하나의 숫자로 표현해야 한다. 이 숫자가 작을수록 모형이 잘 예측한 것이고, 이 숫자를 줄이는 것이 학습의 목표이다.

손실 함수 (Loss Function)

모형의 예측값과 실제값 사이의 오차를 정량화하는 함수.

  • 회귀 문제 → 평균제곱오차 (MSE)
  • 분류 문제 → 교차 엔트로피 (Cross Entropy)
종속변수 y의 유형은? 숫자형 (연속) 범주형 (이산) 회귀 → MSE 1/n · Σ(yᵢ − ŷᵢ)² 예: 연봉, 키, 온도 예측 분류 → Cross Entropy −Σ yₖ log ŷₖ 예: 스팸 판별, 이미지 분류

5.2.2 평균제곱오차 (MSE)

회귀 문제에서 가장 널리 사용되는 손실 함수이다.

\[\text{MSE} = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2\]

  • \(y_i\): 실제값
  • \(\hat{y}_i\): 예측값
  • \(n\): 데이터 개수

5.2.2.1 수치 예시

5명의 키(cm)를 예측하는 모형이 있다고 하자.

코드
import pandas as pd

actual =    [170, 165, 180, 175, 160]
predicted = [168, 170, 178, 172, 163]

rows = []
total_sq = 0
for i, (y, yh) in enumerate(zip(actual, predicted), 1):
    err = y - yh
    sq = err ** 2
    total_sq += sq
    rows.append({
        '데이터': f'$i={i}$',
        '실제값 $y_i$': y,
        '예측값 $\\hat{{y}}_i$': yh,
        '오차 $(y_i - \\hat{{y}}_i)$': f'{err:+d}',
        '오차² $(y_i - \\hat{{y}}_i)^2$': sq,
    })

mse = total_sq / len(actual)
rows.append({
    '데이터': '**합계 / MSE**',
    '실제값 $y_i$': '',
    '예측값 $\\hat{{y}}_i$': '',
    '오차 $(y_i - \\hat{{y}}_i)$': '',
    '오차² $(y_i - \\hat{{y}}_i)^2$': f'합={total_sq}, **MSE={mse:.1f}**',
})

pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 5.1: MSE 계산 예시 — 키 예측
데이터 실제값 \(y_i\) 예측값 \(\\hat{{y}}_i\) 오차 \((y_i - \\hat{{y}}_i)\) 오차² \((y_i - \\hat{{y}}_i)^2\)
\(i=1\) 170 168 +2 4
\(i=2\) 165 170 -5 25
\(i=3\) 180 178 +2 4
\(i=4\) 175 172 +3 9
\(i=5\) 160 163 -3 9
합계 / MSE 합=51, MSE=10.2

MSE = \(\frac{4+25+4+9+9}{5} = \frac{51}{5} = 10.2\)

5.2.3 교차 엔트로피 (Cross Entropy)

분류 문제에서 사용하는 손실 함수이다.

이진 분류 (Binary Cross Entropy):

\[\text{BCE} = -\frac{1}{n}\sum_{i=1}^{n}\left[y_i \log(\hat{y}_i) + (1-y_i)\log(1-\hat{y}_i)\right]\]

핵심 직관: 정답이 1일 때 \(\hat{y}\)가 1에 가까우면 손실이 작고, 0에 가까우면 손실이 매우 크다.

5.2.3.1 수치 예시

4개의 이진 분류 데이터에서 모형이 다음과 같은 확률을 출력하였다.

코드
import pandas as pd
import numpy as np

actual =    [1, 1, 0, 0]
predicted = [0.9, 0.6, 0.2, 0.8]

rows = []
total_loss = 0
for i, (y, p) in enumerate(zip(actual, predicted), 1):
    loss_i = -(y * np.log(p) + (1-y) * np.log(1-p))
    total_loss += loss_i
    rows.append({
        '데이터': f'$i={i}$',
        '실제값 $y_i$': y,
        '예측 확률 $\\hat{{y}}_i$': p,
        '손실 $-[y\\log\\hat{{y}} + (1-y)\\log(1-\\hat{{y}})]$': f'{loss_i:.4f}',
    })

bce = total_loss / len(actual)
rows.append({
    '데이터': '**BCE**',
    '실제값 $y_i$': '',
    '예측 확률 $\\hat{{y}}_i$': '',
    '손실 $-[y\\log\\hat{{y}} + (1-y)\\log(1-\\hat{{y}})]$': f'**{bce:.4f}**',
})

pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 5.2: Binary Cross Entropy 계산 예시
데이터 실제값 \(y_i\) 예측 확률 \(\\hat{{y}}_i\) 손실 \(-[y\\log\\hat{{y}} + (1-y)\\log(1-\\hat{{y}})]\)
\(i=1\) 1 0.9 0.1054
\(i=2\) 1 0.6 0.5108
\(i=3\) 0 0.2 0.2231
\(i=4\) 0 0.8 1.6094
BCE 0.6122

데이터 4번(\(y=0\)인데 \(\hat{y}=0.8\))의 손실이 가장 크다. 확신 있는 오답에 큰 벌칙을 부여하는 것이 교차 엔트로피의 핵심 특성이다.


인터랙티브 — 예측 확률에 따른 교차 엔트로피 손실

실제 클래스(\(y\))를 선택하고 예측 확률(\(\hat{y}\))을 조절하면, 손실이 어떻게 변하는지 확인할 수 있습니다.

5.2.4 Softmax 함수

다중 클래스 분류(\(K \geq 3\)개 클래스)에서는 출력층의 \(K\)개 노드 값을 확률로 변환해야 한다.

Softmax 함수

\(K\)개의 출력값 \(z_1, z_2, \ldots, z_K\)합이 1인 확률 분포로 변환하는 함수.

\[\text{softmax}(z_k) = \frac{e^{z_k}}{\sum_{j=1}^{K} e^{z_j}}, \quad k = 1, \ldots, K\]

  • 모든 출력이 \((0, 1)\) 범위
  • 모든 출력의 합 = 1
  • \(z_k\) 값에 더 높은 확률 배정
출력층 값 z₁ z₂ z₃ e^z₁ e^z₂ e^z₃ e^zₖ Σe^zⱼ Softmax 확률 P₁ = 65.9% P₂ = 24.2% P₃ = 9.9% 합 = 1.0

5.2.4.1 수치 예시

3개 클래스 분류에서 출력층의 값이 \(z_1=2.0,\ z_2=1.0,\ z_3=0.5\)인 경우:

코드
import pandas as pd
import numpy as np

z = [2.0, 1.0, 0.5]
exp_z = [np.exp(zi) for zi in z]
sum_exp = sum(exp_z)
softmax = [e / sum_exp for e in exp_z]

rows = []
for k in range(3):
    rows.append({
        '클래스': f'$k={k+1}$',
        '$z_k$': z[k],
        '$e^{{z_k}}$': f'{exp_z[k]:.4f}',
        '$\\text{{softmax}}(z_k)$': f'{softmax[k]:.4f}',
        '확률 (%)': f'{softmax[k]*100:.1f}%',
    })

rows.append({
    '클래스': '**합계**',
    '$z_k$': '',
    '$e^{{z_k}}$': f'{sum_exp:.4f}',
    '$\\text{{softmax}}(z_k)$': f'{sum(softmax):.4f}',
    '확률 (%)': '100.0%',
})

pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 5.3: Softmax 계산 과정
클래스 \(z_k\) \(e^{{z_k}}\) \(\\text{{softmax}}(z_k)\) 확률 (%)
\(k=1\) 2.0 7.3891 0.6285 62.9%
\(k=2\) 1.0 2.7183 0.2312 23.1%
\(k=3\) 0.5 1.6487 0.1402 14.0%
합계 11.7561 1.0000 100.0%

가장 큰 \(z\) 값(\(z_1=2.0\))이 가장 높은 확률(65.9%)을 받는다. 이 확률에 대해 교차 엔트로피 손실을 계산한다.

5.2.5 다중 클래스 교차 엔트로피

Softmax 출력에 대한 교차 엔트로피:

\[\mathcal{L} = -\sum_{k=1}^{K} y_k \log(\hat{y}_k)\]

여기서 \(y_k\)는 원-핫 인코딩된 정답 벡터이다. 정답 클래스만 \(y_k=1\)이므로:

\[\mathcal{L} = -\log(\hat{y}_{\text{정답 클래스}})\]

위 예시에서 정답이 클래스 1이면: \(\mathcal{L} = -\log(0.6590) = 0.4170\)


인터랙티브 — Softmax 계산기

3개 클래스의 출력값을 조절하면, Softmax 확률과 손실이 실시간으로 계산됩니다.


5.3 기울기: 조금 바꾸면 얼마나 변하는가

손실 함수를 정의했으니 이제 손실을 줄여야 한다. 그런데 파라미터를 어느 쪽으로 움직여야 손실이 줄어드는지 어떻게 아는가?

그 방향을 알려주는 것이 기울기다. 미분을 배운 적이 없어도 괜찮다 — 기울기는 사실 아주 단순한 질문 하나에 대한 답이다.

“파라미터를 아주 조금 바꾸면, 손실은 얼마나 변하는가?”

5.3.1 미분을 모르고 시작하기 — 숫자로 직접 확인

손실 함수가 \(\mathcal{L}(\theta) = (\theta - 3)^2\) 이고, 현재 \(\theta = 0\) 이라 하자.

현재 손실은 \(\mathcal{L}(0) = (0-3)^2 = 9\) 다. 여기서 \(\theta\)0.001만큼 아주 조금 늘려 보자.

\[\mathcal{L}(0.001) = (0.001 - 3)^2 = (-2.999)^2 = 8.994001\]

손실이 \(9 \to 8.994001\)줄었다. 얼마나 줄었는가?

\[\frac{\text{손실의 변화}}{\theta\text{의 변화}} = \frac{8.994001 - 9}{0.001} = \frac{-0.005999}{0.001} = -5.999\]

\(-5.999\) 라는 숫자가 말해주는 것은 두 가지다.

  • 부호(−): \(\theta\)를 늘리면 손실이 줄어든다\(\theta\)를 키워야 한다
  • 크기(약 6): \(\theta\)를 1 늘리면 손실이 대략 6쯤 줄어드는 가파른 경사다
코드
import pandas as pd

def L(t):
    return (t - 3) ** 2

rows = []
for h in [1.0, 0.1, 0.01, 0.001, 0.0001]:
    rate = (L(0 + h) - L(0)) / h
    rows.append({
        '변화폭 $h$': h,
        r'$\mathcal{L}(0+h)$': round(L(h), 8),
        '변화율 $(\\mathcal{L}(0+h) - \\mathcal{L}(0))\\,/\\,h$': round(rate, 6),
    })

pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 5.4: 변화폭을 줄여갈수록 변화율이 하나의 값(−6)으로 수렴한다
변화폭 \(h\) \(\\mathcal{L}(0+h)\) 변화율 \((\\mathcal{L}(0+h) - \\mathcal{L}(0))\\,/\\,h\)
1.0000 4.000000 -5.0000
0.1000 8.410000 -5.9000
0.0100 8.940100 -5.9900
0.0010 8.994001 -5.9990
0.0001 8.999400 -5.9999

변화폭 \(h\)를 점점 줄이면 변화율이 정확히 \(-6\) 으로 수렴한다. 이 극한값이 바로 미분이다.

미분 (Derivative)

어떤 점에서 입력을 아주 조금 바꿨을 때 출력이 변하는 비율.

\[\frac{d\mathcal{L}}{d\theta} = \lim_{h \to 0} \frac{\mathcal{L}(\theta + h) - \mathcal{L}(\theta)}{h}\]

기하학적으로는 그 점에서 그은 접선의 기울기다. “\(\theta\)를 1만큼 늘리면 \(\mathcal{L}\)이 이만큼 변한다”의 순간 버전이라고 읽으면 된다.

5.3.2 이 수업에서 필요한 미분 공식은 셋뿐

미분을 처음부터 배울 필요는 없다. 이 수업에서 쓰는 것은 다음 세 줄이 전부다.

# 규칙
상수는 미분하면 0 \((7)' = 0\)
\(\theta^n\) 은 미분하면 \(n\,\theta^{\,n-1}\) \((\theta^2)' = 2\theta\),   \((\theta)' = 1\)
더하기는 각각 미분해서 더한다 \((\theta^2 - 6\theta + 9)' = 2\theta - 6 + 0\)

여기에 Ch04에서 연쇄법칙 하나만 더 배우면, 딥러닝 역전파에 필요한 미분은 끝난다.

5.3.3 ✍️ 손으로 따라 계산하기 ① — 공식으로 구한 값이 숫자와 맞는가

\(\mathcal{L}(\theta) = (\theta - 3)^2\) 의 도함수를 위 세 규칙만으로 구해 보자.

단계 1 — 괄호를 전개한다.

\[\mathcal{L}(\theta) = (\theta - 3)^2 = \theta^2 - 6\theta + 9\]

단계 2 — 항마다 규칙을 적용한다 (규칙 ③: 각각 미분해서 더한다).

\[ \begin{aligned} (\theta^2)' &= 2\theta && \text{규칙 ②} \\ (-6\theta)' &= -6 && \text{규칙 ② ($\theta^1 \to 1$), 계수는 그대로} \\ (9)' &= 0 && \text{규칙 ①} \end{aligned} \]

단계 3 — 더한다.

\[\frac{d\mathcal{L}}{d\theta} = 2\theta - 6 = 2(\theta - 3)\]

단계 4 — 검산. \(\theta = 0\)을 넣으면 \(2(0-3) = \mathbf{-6}\). 앞에서 숫자로 구한 \(-5.999\)와 일치한다. ✅

공식으로 구한 미분과 숫자로 두드려 본 값이 같다 — 미분은 마법이 아니라 “조금 바꿔보기”의 지름길일 뿐이다.

5.3.4 파라미터가 둘 이상일 때 — 편미분

실제 신경망의 파라미터는 하나가 아니다. 가중치와 편향만 해도 둘이고, 층이 쌓이면 수백만 개다.

파라미터가 \(w\)\(b\) 두 개라면, 손실은 \(\mathcal{L}(w, b)\) 처럼 두 입력의 함수가 된다. 이때도 질문은 똑같다 — 다만 하나씩 묻는다.

\(b\)는 그대로 두고 \(w\) 조금 바꾸면, 손실은 얼마나 변하는가?”

편미분 (Partial Derivative)

입력이 여러 개인 함수에서, 나머지를 전부 상수로 붙잡아 두고 하나만 미분하는 것.

\[\frac{\partial \mathcal{L}}{\partial w} \quad \text{— "}\partial\text{"는 '라운드' 또는 '델'이라고 읽는다}\]

기호만 \(d\)에서 \(\partial\)로 바뀔 뿐, 계산 방법은 보통 미분과 완전히 같다. 달라지는 것은 태도 하나다 — 지금 미분하지 않는 변수는 숫자처럼 취급한다.

5.3.5 ✍️ 손으로 따라 계산하기 ② — 편미분 두 개 구하기

\[\mathcal{L}(w, b) = 3w^2 + 2wb + b^2\]

\(w\)에 대한 편미분\(b\)상수로 붙잡는다. (\(b\)를 그냥 숫자 5쯤이라고 생각하면 쉽다.)

\(b\)를 상수로 보면 \(w\)로 미분하면
\(3w^2\) \(w\)의 2차항 \(6w\)
\(2wb\) \((2b) \times w\) — 즉 상수 × \(w\) \(2b\)
\(b^2\) 완전히 상수 \(0\)

\[\frac{\partial \mathcal{L}}{\partial w} = 6w + 2b\]

\(b\)에 대한 편미분 — 이번엔 \(w\)를 상수로 붙잡는다.

\(w\)를 상수로 보면 \(b\)로 미분하면
\(3w^2\) 완전히 상수 \(0\)
\(2wb\) \((2w) \times b\) \(2w\)
\(b^2\) \(b\)의 2차항 \(2b\)

\[\frac{\partial \mathcal{L}}{\partial b} = 2w + 2b\]

검산해 보자. \(w = 1,\ b = 2\) 일 때 \(\dfrac{\partial \mathcal{L}}{\partial w} = 6(1) + 2(2) = 10\) 이어야 한다.

숫자로 두드려 보면 — \(\mathcal{L}(1, 2) = 3 + 4 + 4 = 11\), \(\mathcal{L}(1.001, 2) = 3(1.002001) + 2(1.001)(2) + 4 = 11.010005\).

\[\frac{11.010005 - 11}{0.001} = 10.005 \;\approx\; 10 \quad ✅\]

\(\mathcal{L}(w, b) = w^2 b + 4b - 7\)\(\dfrac{\partial \mathcal{L}}{\partial w}\)\(\dfrac{\partial \mathcal{L}}{\partial b}\) 를 구하라.

정답 펼치기

\(w\)로 편미분 (\(b\)는 상수):

  • \(w^2 b\)\(b\)가 계수인 \(w\)의 2차항 → \(2wb\)
  • \(4b\) → 상수 → \(0\)
  • \(-7\) → 상수 → \(0\)

\[\frac{\partial \mathcal{L}}{\partial w} = 2wb\]

\(b\)로 편미분 (\(w\)는 상수):

  • \(w^2 b\)\(w^2\)가 계수인 \(b\)의 1차항 → \(w^2\)
  • \(4b\)\(4\)
  • \(-7\)\(0\)

\[\frac{\partial \mathcal{L}}{\partial b} = w^2 + 4\]

여기까지가 이 수업에서 필요한 미분의 전부다. 규칙 3개 + “나머지는 상수로 붙잡는다”는 태도 하나. Ch04에서 연쇄법칙 하나만 더 얹으면 역전파를 손으로 계산할 수 있다.


5.4 경사하강법 (Gradient Descent)

5.4.1 직관: 산을 내려가기

손실 함수의 값을 줄이려면, 파라미터를 어떤 방향으로 바꿔야 할까?

경사하강법 (Gradient Descent)

손실 함수의 그래디언트(기울기) 반대 방향으로 파라미터를 조금씩 이동시키는 최적화 알고리즘.

\[\theta_{\text{new}} = \theta_{\text{old}} - \eta \cdot \frac{\partial \mathcal{L}}{\partial \theta}\]

  • \(\eta\): 학습률 (learning rate) — 한 번에 이동하는 보폭
  • \(\frac{\partial \mathcal{L}}{\partial \theta}\): 손실 함수의 기울기 — 이동할 방향

5.4.2 왜 “반대 방향”인가?

  • 기울기가 양수 → 파라미터를 키우면 손실이 증가 → 줄여야
  • 기울기가 음수 → 파라미터를 키우면 손실이 감소 → 키워야
  • 따라서 기울기의 반대 방향으로 이동해야 손실이 줄어든다

5.4.3 수치 예시: 1차원 경사하강법

\(\mathcal{L}(\theta) = (\theta - 3)^2\)이라 하자. 최솟값은 \(\theta = 3\)에서 달성된다.

  • 도함수: \(\frac{d\mathcal{L}}{d\theta} = 2(\theta - 3)\)
  • 학습률: \(\eta = 0.1\)
  • 초기값: \(\theta_0 = 0\)
코드
import pandas as pd

theta = 0.0
eta = 0.1
rows = []

for step in range(8):
    loss = (theta - 3) ** 2
    grad = 2 * (theta - 3)
    rows.append({
        'Step': step,
        '$\\theta$': f'{theta:.4f}',
        '$\\mathcal{{L}}(\\theta) = (\\theta-3)^2$': f'{loss:.4f}',
        '$\\frac{{d\\mathcal{{L}}}}{{d\\theta}} = 2(\\theta-3)$': f'{grad:.4f}',
        '$\\theta_{\\text{new}} = \\theta - 0.1 \\cdot \\nabla$': f'{theta - eta * grad:.4f}',
    })
    theta = theta - eta * grad

pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 5.5: 경사하강법 수치 예시 — L(θ) = (θ−3)²
Step \(\\theta\) \(\\mathcal{{L}}(\\theta) = (\\theta-3)^2\) \(\\frac{{d\\mathcal{{L}}}}{{d\\theta}} = 2(\\theta-3)\) \(\\theta_{\\text{new}} = \\theta - 0.1 \\cdot \\nabla\)
0 0.0000 9.0000 -6.0000 0.6000
1 0.6000 5.7600 -4.8000 1.0800
2 1.0800 3.6864 -3.8400 1.4640
3 1.4640 2.3593 -3.0720 1.7712
4 1.7712 1.5099 -2.4576 2.0170
5 2.0170 0.9664 -1.9661 2.2136
6 2.2136 0.6185 -1.5729 2.3709
7 2.3709 0.3958 -1.2583 2.4967

매 스텝마다 \(\theta\)가 3에 가까워지고, 손실이 줄어드는 것을 확인할 수 있다.

5.4.4 ✍️ 손으로 따라 계산하기 ③ — 진짜 신경망 파라미터로 1스텝

\(\mathcal{L}(\theta) = (\theta-3)^2\) 은 연습용 함수였다. 이제 실제 신경망의 파라미터로 같은 일을 해 보자.

가장 작은 신경망 — 퍼셉트론 하나, 활성화는 항등함수 — 을 데이터 한 건으로 학습한다.

\[\hat{y} = w x + b, \qquad \mathcal{L} = (y - \hat{y})^2\]

설정: 데이터 \((x = 2,\ y = 5)\), 현재 파라미터 \(w = 1.0,\ b = 0.5\), 학습률 \(\eta = 0.05\).

이 공식은 일단 받아들이고 쓴다

\[\frac{\partial \mathcal{L}}{\partial w} = -2(y - \hat{y})\,x, \qquad \frac{\partial \mathcal{L}}{\partial b} = -2(y - \hat{y})\]

이 두 식이 어디서 나오는지는 Ch04에서 연쇄법칙으로 직접 유도한다. 지금은 공식으로 쓰되, 아래 단계 5에서 이 공식이 맞는지 숫자로 검산한다.

단계 1 — 순전파. 지금 파라미터로 예측해 본다.

\[\hat{y} = 1.0 \times 2 + 0.5 = 2.5\]

단계 2 — 손실. 얼마나 틀렸는가?

\[\mathcal{L} = (5 - 2.5)^2 = 2.5^2 = 6.25\]

단계 3 — 그래디언트. 오차 \((y - \hat{y}) = 5 - 2.5 = 2.5\) 를 먼저 구해 두면 편하다.

\[ \begin{aligned} \frac{\partial \mathcal{L}}{\partial w} &= -2 \times 2.5 \times 2 = -10 \\[2pt] \frac{\partial \mathcal{L}}{\partial b} &= -2 \times 2.5 = -5 \end{aligned} \]

둘 다 음수다 → \(w\)\(b\)키워야 손실이 줄어든다. (예측 2.5가 정답 5보다 작으니 당연하다.)

단계 4 — 갱신. 기울기의 반대 방향으로 학습률만큼 이동한다.

\[ \begin{aligned} w_{\text{new}} &= 1.0 - 0.05 \times (-10) = 1.0 + 0.5 = \mathbf{1.5} \\ b_{\text{new}} &= 0.5 - 0.05 \times (-5) = 0.5 + 0.25 = \mathbf{0.75} \end{aligned} \]

단계 5 — 정말 나아졌는가? 새 파라미터로 다시 순전파한다.

\[\hat{y}_{\text{new}} = 1.5 \times 2 + 0.75 = 3.75, \qquad \mathcal{L}_{\text{new}} = (5 - 3.75)^2 = 1.5625\]

손실이 \(6.25 \to 1.5625\) 로 줄었다. ✅ 학습 1스텝이 끝났다.

코드
import pandas as pd

x, y, w, b, eta = 2.0, 5.0, 1.0, 0.5, 0.05

yh = w * x + b
loss = (y - yh) ** 2
gw = -2 * (y - yh) * x
gb = -2 * (y - yh)
w2, b2 = w - eta * gw, b - eta * gb
yh2 = w2 * x + b2
loss2 = (y - yh2) ** 2

rows = [
    {'단계': '① 순전파',   '계산': f'ŷ = {w}×{x} + {b}',           '결과': yh},
    {'단계': '② 손실',     '계산': f'({y}{yh})²',                '결과': loss},
    {'단계': '③ 그래디언트', '계산': f'∂L/∂w = −2×{y-yh}×{x}',       '결과': gw},
    {'단계': '③ 그래디언트', '계산': f'∂L/∂b = −2×{y-yh}',           '결과': gb},
    {'단계': '④ 갱신',     '계산': f'w ← {w}{eta}×({gw})',        '결과': w2},
    {'단계': '④ 갱신',     '계산': f'b ← {b}{eta}×({gb})',        '결과': b2},
    {'단계': '⑤ 검산',     '계산': f'새 손실 ({y}{yh2})²',        '결과': round(loss2, 4)},
]
pd.DataFrame(rows).to_html(index=False, border=0)
표 5.6: 퍼셉트론 파라미터의 경사하강 1스텝 — 단계별 값
단계 계산 결과
① 순전파 ŷ = 1.0×2.0 + 0.5 2.5000
② 손실 (5.0 − 2.5)² 6.2500
③ 그래디언트 ∂L/∂w = −2×2.5×2.0 -10.0000
③ 그래디언트 ∂L/∂b = −2×2.5 -5.0000
④ 갱신 w ← 1.0 − 0.05×(-10.0) 1.5000
④ 갱신 b ← 0.5 − 0.05×(-5.0) 0.7500
⑤ 검산 새 손실 (5.0 − 3.75)² 1.5625

공식이 맞는지 숫자로 검산해 보자. 처음 상태(\(w = 1.0\))에서 \(w\)\(0.001\) 늘리면:

\[\hat{y} = 1.001 \times 2 + 0.5 = 2.502, \qquad \mathcal{L} = (5 - 2.502)^2 = 6.240004\]

\[\frac{6.240004 - 6.25}{0.001} = -9.996 \;\approx\; -10 \quad ✅\]

공식 \(\partial \mathcal{L}/\partial w = -10\) 과 일치한다. 유도는 못 했어도, 공식이 옳다는 것은 이렇게 스스로 확인할 수 있다.

방금 갱신한 \(w = 1.5,\ b = 0.75\) 에서 한 스텝 더 진행하면 \(w\)\(b\)는 얼마가 되는가? (같은 데이터 \(x=2,\ y=5\), 같은 \(\eta = 0.05\))

정답 펼치기

\(\hat{y} = 1.5 \times 2 + 0.75 = 3.75\)

② 오차 \(= 5 - 3.75 = 1.25\)

\(\partial \mathcal{L}/\partial w = -2 (1.25)(2) = -5\),   \(\partial \mathcal{L}/\partial b = -2(1.25) = -2.5\)

\(w = 1.5 - 0.05(-5) = \mathbf{1.75}\),   \(b = 0.75 - 0.05(-2.5) = \mathbf{0.875}\)

\(\hat{y} = 1.75(2) + 0.875 = 4.375\),   손실 \(= (5-4.375)^2 = 0.3906\)

손실이 \(1.5625 \to 0.3906\) 으로 또 줄었다. 그래디언트의 크기도 함께 줄어드는 것에 주목하라 — 정답에 가까워질수록 걸음도 자연히 작아진다.

연습을 더 하려면: 도장 3주차의 유형 E·F가 정확히 이 계산이다.


인터랙티브 — 경사하강법 시뮬레이션

학습률과 초기값을 조절하며 경사하강법이 어떻게 작동하는지 확인하세요.

시도해 보세요: 학습률을 0.9 이상으로 올리면 발산하는 모습을, 0.01로 낮추면 매우 느리게 수렴하는 모습을 확인할 수 있습니다.

5.4.5 2차원 경사하강법 — 등고선 시각화

실제 신경망은 파라미터가 여러 개이므로, 2차원 이상의 손실 표면 위에서 경사하강법이 작동한다. \(\mathcal{L}(\theta_1, \theta_2) = (\theta_1 - 2)^2 + 3(\theta_2 - 1)^2\)에서 최솟값 \((2, 1)\)을 향해 이동하는 과정을 시각화한다.


인터랙티브 — 2D 등고선 위의 경사하강법

학습률을 조절하며 2차원 손실 표면 위에서 그래디언트 경로가 어떻게 변하는지 확인하세요.

화살표의 의미: 각 스텝에서 빨간 화살표는 \(-\nabla\mathcal{L}\) 방향, 즉 손실이 가장 빠르게 줄어드는 방향을 나타낸다. \(\theta_2\) 방향 기울기(\(\times 3\))가 더 가파르므로 화살표가 \(\theta_2\) 축으로 더 길게 뻗는 것을 확인할 수 있다.


5.5 신경망의 학습 과정 — 전체 그림

지금까지 손실 함수와 경사하강법을 각각 배웠다. 이제 이들이 실제 신경망에서 어떻게 하나의 학습 루프로 결합되는지 전체 흐름을 정리한다.

5.5.1 순전파 → 손실 → 역전파 → 갱신

신경망 학습의 4단계
단계 이름 하는 일
순전파 (Forward Pass) 입력 \(X\)를 신경망에 통과시켜 예측값 \(\hat{y}\) 계산
손실 계산 예측값과 정답의 오차를 손실 함수로 측정: \(\mathcal{L}(y, \hat{y})\)
역전파 (Backpropagation) 손실을 각 파라미터로 편미분하여 그래디언트 \(\frac{\partial \mathcal{L}}{\partial \theta}\) 계산
파라미터 갱신 경사하강법으로 파라미터 업데이트: \(\theta \leftarrow \theta - \eta \nabla\mathcal{L}\)

이 4단계를 1회 반복하는 것을 이터레이션(iteration)이라 하고, 전체 데이터를 한 번 다 사용하는 것을 에폭(epoch)이라 한다.

5.5.2 인터랙티브 — 데이터를 한 건씩 학습하는 과정

단순한 퍼셉트론 \(\hat{y} = wx + b\)가 4개의 데이터를 한 건씩 학습하는 과정을 따라가 보자. “다음 스텝”을 누를 때마다 순전파 → 손실 → 역전파 → 갱신이 한 번 일어난다.

노트

③ 역전파에 나오는 \(\partial\mathcal{L}/\partial w\) 수식이 어디서 오는지(연쇄법칙)는 다음 장에서 직접 손으로 유도한다. 여기서는 “기울기를 계산해서 그 반대 방향으로 움직인다”는 전체 흐름에 집중하자.

스텝을 진행할수록 직선이 데이터에 맞춰지고, 전체 MSE가 줄어드는 것을 관찰할 수 있다. 4개의 데이터를 한 바퀴 도는 것이 1 에폭이다.

이 학습 루프에서 사용자가 직접 설정해야 하는 값이 있다 — 바로 학습률 \(\eta\)배치 크기이다. 이 두 가지는 다음 장(Ch04)에서 실험과 함께 다룬다.


5.6 핵심 요약

개념 핵심 내용
학습 손실 함수를 최소화하는 파라미터를 찾는 과정
MSE 회귀 손실 함수: \(\frac{1}{n}\sum(y_i - \hat{y}_i)^2\)
교차 엔트로피 분류 손실 함수: \(-\sum y_k \log \hat{y}_k\)
Softmax 출력을 확률 분포로 변환: \(\frac{e^{z_k}}{\sum e^{z_j}}\)
경사하강법 \(\theta_{\text{new}} = \theta - \eta \cdot \nabla\mathcal{L}\)
학습 루프 순전파 → 손실 → 역전파 → 갱신의 반복 (1바퀴 = 이터레이션, 전체 데이터 1회 = 에폭)