계산주의와 인지신경과학 6주차_학습의 원리 #2: 델타 규칙(delta rule)과 오차 역전파 기초

고려대학교 일반대학원 심리학과

Published

2026년 4월 10일 금요일 4-5교시

6주차 수업 목표

  • 패러다임의 전환 (맹목적 수용에서 비판적 수정으로): 단순 동시 활성화에만 의존하여 무한 덧셈을 수행하던 헵 규칙(Hebbian learning)의 한계를 비판적으로 검토하고, 오차를 기반으로 가중치를 정교하게 깎아내는 델타 규칙(delta rule)의 철학적, 수학적 원리를 심층적으로 이해함.
  • 학습 심리학과의 수학적 조우: 델타 규칙이 동물 학습 심리학의 금자탑인 ’레스콜라-와그너(Rescorla-Wagner) 모델’과 어떻게 수학적으로 완벽히 동일한지 규명하고, ’예측오차(prediction error)’가 인지 시스템의 핵심 학습 동력임을 체화함.
  • 경사하강법(gradient descent)의 직관적 체화: 미분과 기울기의 개념을 ’안대 낀 등산객이 산을 내려가는 과정’에 비유하여, 고차원 손실 공간(loss landscape)에서의 파라미터 최적화 원리와 학습률(learning rate)의 중요성을 파악함.
  • 파국적 간섭(catastrophic interference)의 수학적 통제: 오차 수정 메커니즘이 비직교(non-orthogonal) 패턴 간의 특징 겹침 문제를 어떻게 스스로 억제하고 튜닝해내는지 파이썬 코드로 증명함.
  • 기여도 할당 문제(credit assignment problem)와 오차 역전파: 다층 퍼셉트론(multi-layer perceptron, MLP)의 은닉층이 갖는 인지적 내부 표상(internal representation)의 의미를 이해하고, 미분의 연쇄법칙(chain rule)을 통해 최종 오차의 ’책임’을 하위 뉴런들에게 거꾸로 분배하는 역전파(backpropagation) 알고리즘을 코드로 구현함.

[그림 1] 학습의 원리 #2: 델타 규칙(delta rule)과 오차 역전파 기초

1부: 맹목적 덧셈에서 오차 기반 수정으로(델타 규칙)

1.1. 패러다임의 전환: 헵 규칙의 비극과 델타 규칙의 탄생

[그림 2] 학습 모델의 3단계 진화

  • 이론적 배경(5주차 복기)
    • 헵 규칙의 맹점: 5주차에서 확인했듯, 헵 규칙은 두 뉴런이 활성화되기만 하면 무조건 가중치를 증가시킴(\(\Delta w = \eta \cdot x \cdot y\)). 이는 데이터의 맥락이나 시스템이 목표로 하는 정답 여부를 전혀 고려하지 않는 ’맹목적인 덧셈 기계’에 불과함.
    • 시스템 붕괴: 사과와 토마토처럼 특징(빨갛다, 둥글다)이 겹치는 비직교 패턴이 연달아 입력되면, 겹치는 시냅스의 가중치만 \(+3\), \(+4\)로 무한 누적됨(가중치 폭주). 결국 단서를 주었을 때 사과와 토마토가 기괴하게 섞인 프랑켄슈타인 기억이 인출되는 ’파국적 간섭’이 발생함.
  • 델타 규칙(delta rule)의 철학
    • 버나드 위드로우(Bernard Widrow)와 마시안 호프(Marcian Hoff)가 제안한 위드로우-호프 규칙(Widrow-Hoff rule)으로도 불림. 현대 기계학습의 뼈대를 이룬 공식 중 하나임.
    • 핵심 철학: “학습은 오직 ’기대’와 ’실제’가 다를 때, 즉 놀랐을 때(surprise)만 일어난다.”
    • 정답(target, \(T\))과 현재 인공신경망의 예측값(output, \(Y\))을 비교하여, 틀린 만큼만(error, \(\delta\)) 가중치를 고치는 피드백 기반의 지도 학습(supervised learning) 메커니즘임.
    • 수식: \(\Delta w = \eta \cdot (T - Y) \cdot X\)
      • \(\eta\)
        • 학습률: 한 번의 오차를 발견했을 때 가중치를 얼마나 크게 수정할 것인가를 결정하는 보폭.
        • 설명
          • 가정: 목표 정답(target)이 1.0인데, 신경망의 현재 예측치(output)가 0.0이었다고 가정해보자.
          • 오차: 정답 1.0 - 예측치 0.0 = 1.0 \(\Rightarrow\) 현재 1.0만큼 틀렸음!
          • 오버슈팅(overshooting)의 위험: 이때 신경망이 “아! 내가 1.0만큼 틀렸구나! 당장 가중치(w)에 1.0을 더해서 100% 고쳐야지!”라고 해버리면, 데이터에 섞인 약간의 노이즈나 예외상황 때문에 정답을 지나쳐 엉뚱한 곳으로 튕겨나갈 위험이 큼.
          • 그래서 델타 규칙 공식 중간에 학습률(\(\eta\)) = 0.2이라는 안전장치를 걸어둠. \(\Rightarrow\) 가중치 수정량: 0.2(학습률) * 1.0(오차) * 1(입력) = 0.2.
          • “내가 1.0만큼 틀린 건 알겠지만, 한 번에 다 고치면 위험하니까 이번 턴(epoch)에는 그 오차의 20%인 0.2만큼만 가중치를 살짝 고쳐보자!”라고 타협하는 것.
      • \((T - Y)\): 오차(\(\delta\)). 목표값에서 실제 출력값을 뺀 값. 이것이 가중치 변화의 ’방향’과 ’크기’를 동시에 결정함.
      • \(X\): 입력값. 오차를 발생시키는 데 기여한 바로 그 뉴런의 신호.
  • 심화 해설
    • 오차 제로(\(0\))의 법칙: 만약 신경망이 이미 정답을 완벽하게 맞혔다면(\(T = Y\)), 오차\((T - Y)\)\(0\)이 됨. 수식에 따라 가중치 변화량(\(\Delta w\))도 \(0\)이 됨. \(\Rightarrow\) “이미 완벽히 알고 있는 지식에 대해서는 뇌가 더 이상 시냅스 에너지를 낭비하며 가중치를 조작하지 않는다”는 인지적 경제성을 완벽히 구현함.
    • 레스콜라-와그너 모델(Rescorla-Wagner model)과의 조우
      • 델타 규칙과의 유사성: 1972년 발표된 고전적 조건형성의 수학적 모델인 레스콜라-와그너 공식(\(\Delta V = \alpha \beta (\lambda - \Sigma V)\))과 알파벳 기호만 다를 뿐 수학적 원리가 100% 동일함.
      • 모델의 본질: ’놀람’의 수학화
        • 1972년 제안된 고전적 조건형성(파블로프 학습)의 기념비적 수학 모델.
        • 동물은 두 사건(종소리와 밥)이 단순히 “동시에 발생”했다고 맹목적으로 연결하지 않음.
        • 학습은 오직 동물이 예상치 못한 결과에 놀랐을 때(prediction error)만 일어난다고 규명함.
      • 공식의 이해: \(\Delta V = \alpha \beta (\lambda - \Sigma V)\)
        • \(\Delta V\)(학습량): 이번 경험을 통해 새롭게 수정할 단서(종소리)와 결과(밥)의 연합 강도.
        • \(\lambda\)(실제 현실): 실제로 주어진 밥의 유무 및 크기(예: 밥이 주어지면 1).
        • \(\Sigma V\)(기대치 총합): 현재 환경에 있는 모든 단서(종소리, 불빛 등)를 보고 동물이 ‘예상한’ 밥의 크기.
        • \((\lambda - \Sigma V)\)(예측오차): 실제 현실에서 내 예상을 뺀 값. 즉 놀람의 크기.
      • 학습의 역동성(시간 흐름에 따른 변화)
        • 초기 학습: 종소리 직후 밥이 처음 떨어지면 전혀 예상치 못했으므로 크게 놀람(오차 극대화 \(\Rightarrow\) 가파른 학습).
        • 후기 안정화: 경험이 쌓여 종소리만 들어도 밥을 100% 확신하게 되면, 밥이 나와도 더 이상 놀라지 않음(오차 0 \(\Rightarrow\) \(\Delta V\)도 0이 되어 학습 종료).
      • 최대 업적: 차단 효과(blocking effect)의 수학적 증명
        • 현상: 쥐에게 [종소리 \(\rightarrow\) 밥]을 100% 학습시킨 뒤, [종소리+빛 \(\rightarrow\) 밥]을 제시하면 쥐는 새로운 단서인 ’빛’을 학습하지 않음.
        • 원리: 이미 종소리만으로 밥의 등장(\(\lambda=1\))을 완벽히 예측(\(\Sigma V=1\))하고 있기 때문에 예측오차가 \(0\)임.
        • 결론: “뇌는 이미 완벽하게 예측 가능한 결과에 대해서는, 새로운 정보(빛)가 동시에 주어져도 시냅스 에너지를 낭비하며 추가학습을 하지 않는다”는 뇌의 인지적 경제성을 완벽히 증명함.

[그림 3] 학습 심리학과 AI의 완벽한 수학적 조우

  • 비유
    • 헵 규칙(헬스장 근육맨): 양궁 선수가 과녁을 보지도 않고, 화살을 쏠 때마다 무조건 활시위를 당기는 근력을 키우는 맹목적 훈련. 결국 팔 근육만 너무 비대해져서 정밀한 폼이 다 망가짐.
    • 델타 규칙(전문 코칭): 코치(정답 \(T\))가 화살이 과녁 중앙에서 10cm 우측으로 빗나갔다(오차)고 피드백을 주면, 딱 그 10cm를 좌측으로 보정할 만큼만 근육의 각도를 미세하게 수정하는 훈련. 정중앙을 맞추면 훈련(가중치 수정)을 즉각 종료하고 에너지를 보존함.

[그림 4] 맹목적 근육 키우기 vs. 정밀한 영점 조절

[실습 1-1] 델타 규칙의 기본: 오차 기반 단일 가중치 튜닝

  • 오차가 어떻게 가중치 업데이트의 브레이크 역할을 하며 시스템을 스스로 수렴(convergence)하게 만드는지 파이썬 코드로 뜯어보기.

[그림 5] [실습 1-1] 코드 해부: 오차 기반 단일 가중치 튜닝

Code
import numpy as np

# 1. 초기 세팅 (아무것도 모르는 백지 상태의 시냅스)
# 초기 시냅스 가중치: 아직 학습되지 않은 임의의 작은 연결 강도(0.1)를 부여함.
w = 0.1

# 학습률(learning_rate): 한 번의 오차를 발견했을 때 가중치를 얼마나 수정할지(오차의 20%만 반영) 결정함.
learning_rate = 0.2

# 입력 자극: 뇌에 빛 자극신호가 강하게 들어옴(1.0)을 모사함.
x = 1.0

# 목표 정답(target): 빛 자극이 들어왔을 때 신경망이 도달해야 할 이상적인 반응 강도(1.0)를 설정함.
target = 1.0

print("=== [실습 1-1] 델타 규칙: 틀린 만큼만 정밀하게 고친다 ===")
print(f"목표 정답(target): {target}\n")

# 2. 반복 학습(epochs)
# 가중치의 변화과정을 기록하기 위해 빈 리스트를 생성함.
history_w = []

# 1번부터 10번까지 총 10회(epoch)의 반복경험(학습)을 진행함.
for epoch in range(1, 11):

    # 전방 계산(forward pass): 현재의 시냅스 가중치(w)에 입력 신호(x)를 곱하여 신경망의 현재 예측치(output)를 계산함.
    output = w * x                      

    # 오차 계산(error calculation): 목표로 하는 정답(target)에서 현재 신경망의 예측치(output)를 빼서 순수한 오차(error, 델타)를 구함.
    error = target - output             

    # 역방향 수정(backward update): 헵 규칙과 달리 '오차(error)'를 곱해주어 오차가 클수록 크게, 작을수록 작게 가중치 변화량(delta_w)을 통제함.
    delta_w = learning_rate * error * x 

    # 기존 가중치(w)에 새롭게 계산된 변화량(delta_w)을 더해 시냅스 연결 강도를 최종 업데이트함.
    w = w + delta_w                     

    # 변화된 가중치를 나중에 그래프나 로그로 보기 위해 기록 리스트에 추가함.
    history_w.append(w)

    # 매 에포크마다 예측치, 오차, 그리고 수정된 가중치 상태를 화면에 출력하여 모니터링함.
    print(f"[epoch {epoch:2d}] 예측치: {output:.4f} | 오차(error): {error:.4f} | 수정량: +{delta_w:.4f} -> 새 가중치: {w:.4f}")

print("\n-> 통찰: 에포크가 지날수록 예측치가 정답(1.0)에 가까워짐에 따라, 오차(error)는 점점 0으로 줄어듦.")
print("-> 오차가 줄어드니 가중치 수정량(delta_w)도 자연스럽게 0에 수렴하며, 시스템이 폭주하지 않고 스스로 학습을 멈추는 완벽한 항상성(homeostasis)을 보여줌.")
=== [실습 1-1] 델타 규칙: 틀린 만큼만 정밀하게 고친다 ===
목표 정답(target): 1.0

[epoch  1] 예측치: 0.1000 | 오차(error): 0.9000 | 수정량: +0.1800 -> 새 가중치: 0.2800
[epoch  2] 예측치: 0.2800 | 오차(error): 0.7200 | 수정량: +0.1440 -> 새 가중치: 0.4240
[epoch  3] 예측치: 0.4240 | 오차(error): 0.5760 | 수정량: +0.1152 -> 새 가중치: 0.5392
[epoch  4] 예측치: 0.5392 | 오차(error): 0.4608 | 수정량: +0.0922 -> 새 가중치: 0.6314
[epoch  5] 예측치: 0.6314 | 오차(error): 0.3686 | 수정량: +0.0737 -> 새 가중치: 0.7051
[epoch  6] 예측치: 0.7051 | 오차(error): 0.2949 | 수정량: +0.0590 -> 새 가중치: 0.7641
[epoch  7] 예측치: 0.7641 | 오차(error): 0.2359 | 수정량: +0.0472 -> 새 가중치: 0.8113
[epoch  8] 예측치: 0.8113 | 오차(error): 0.1887 | 수정량: +0.0377 -> 새 가중치: 0.8490
[epoch  9] 예측치: 0.8490 | 오차(error): 0.1510 | 수정량: +0.0302 -> 새 가중치: 0.8792
[epoch 10] 예측치: 0.8792 | 오차(error): 0.1208 | 수정량: +0.0242 -> 새 가중치: 0.9034

-> 통찰: 에포크가 지날수록 예측치가 정답(1.0)에 가까워짐에 따라, 오차(error)는 점점 0으로 줄어듦.
-> 오차가 줄어드니 가중치 수정량(delta_w)도 자연스럽게 0에 수렴하며, 시스템이 폭주하지 않고 스스로 학습을 멈추는 완벽한 항상성(homeostasis)을 보여줌.

1.2. 경사하강법(gradient descent)과 손실공간(loss landscape)

  • 이론적 설명
    • 델타 규칙은 인지 모델링의 언어이지만, 이를 공학과 수학의 언어로 번역하면 최적화 알고리즘의 핵심 뼈대인 경사하강법(gradient descent)과 완벽히 일치함.
    • 인공신경망 학습의 궁극적인 목표는 수만 개의 시냅스 가중치(\(W\))들이 뱉어내는 수많은 예측오차들을 전부 모아 제곱하여 더한 총 손실(total loss, 비용 함수)의 값을 수학적으로 가장 작게(최소화) 만드는 완벽한 가중치 조합을 찾는 것임.
  • 심화 해설(기하학적 이해)
    • 손실 공간(loss landscape): 가로축을 가중치(\(W\)), 세로축을 오차(loss)로 두면, 허공에 거대한 밥그릇 모양의 2차 함수 곡선 지형도가 그려짐.
    • 미분(derivative)의 역할: 미분은 현재 가중치 위치에서 지형의 ’기울기(가파른 정도와 방향)’를 알려주는 나침반임. 기울기가 양수(+)면 오른쪽이 오르막이란 뜻이고, 음수(-)면 오른쪽이 내리막이란 뜻.
    • 경사하강(descent): 오차를 줄이려면 오르막(기울기)의 정반대 방향(마이너스 부호 적용)으로 걸음을 내디뎌야 함. 이를 수식화한 것이 \(W_{new} = W_{old} - \eta \cdot \nabla L\) 이며, 여기서 손실 함수의 미분값(\(\nabla L\))을 풀면 정확히 델타 규칙의 \((Y-T) \cdot X\) 형태가 도출됨.
    • 학습률(\(\eta\))의 딜레마:
      • 보폭(\(\eta\))이 너무 작으면 바닥에 도달하기까지 천년 만년이 걸리거나, 중간에 있는 얕은 웅덩이(local minimum)에 빠져 갇혀버림(과소 적합).
      • 보폭(\(\eta\))이 너무 크면 계곡 반대편 언덕으로 튕겨 나가며 오차가 걷잡을 수 없이 더 커지는 발산(overshooting) 현상이 일어남. 모델 피팅(model fitting) 시 가장 주의해야 할 하이퍼파라미터임.
  • 비유
    • 안대 낀 등산객: 짙은 안개가 낀 거대한 분지 지형(한라산 백록담) 한가운데에 안대를 낀 등산객(신경망)이 헬기에서 떨어짐. 이 사람의 목표는 가장 고도가 낮은 골짜기 밑바닥(loss = \(0\))을 찾는 것임.
    • 지도가 없으니 오직 발바닥에 느껴지는 현재 땅의 경사(미분값)만 느낌. 앞꿈치가 들려있으면(오르막), 뒤로 한 걸음 물러섬. 뒤꿈치가 들려있으면 앞으로 한 걸음 감.
    • 이 ‘가장 가파른 내리막을 향해 한 걸음씩 걷는’ 무식하지만 확실한 반복행위가 바로 딥러닝과 인지 모델을 학습시키는 경사하강법의 본질임.

[그림 6] 손실 공간과 안대 낀 등산객

[실습 1-2] 학습률에 따른 경사하강법의 발산과 수렴 비교

  • 학습률(보폭) 설정에 따라 모델이 정답을 향해 우아하게 내려가는지(수렴), 아니면 계곡 밖으로 튕겨 나가는지(발산) 코드를 통해 극명한 차이를 확인.

[그림 7] [실습 1-2] 학습률(\(\eta\))의 딜레마: 수렴과 발산

Code
import numpy as np

# 1. 동일한 문제 환경 세팅
# 비교를 위해 입력 신호(x)와 도달해야 할 정답(target)을 1.0으로 동일하게 고정함.
x = 1.0
target = 1.0

# 2. 신경망 두 개의 가중치 및 학습률 차별 세팅
# 첫 번째 신경망: 정상적인 신경망(w_good)
w_good = 0.1          # 정상 신경망의 초기 가중치
lr_good = 0.2         # 적당한 보폭으로 설정한 정상 학습률(안정적 수렴을 유도함)

# 두 번째 신경망: 문제가 있는 신경망(w_bad)
w_bad = 0.1           # 문제 신경망의 초기 가중치(출발선은 동일함)
lr_bad = 1.5          # 의도적으로 너무 큰 보폭으로 설정한 과다 학습률(계곡 반대편으로 튕겨 나가는 발산을 유도함)

print("=== [실습 1-2] 학습률의 마법과 저주 ===")
print("목표: 가중치(w)가 1.0에 도달해야 함.\n")

# 3. 경사하강법 5회 반복 시뮬레이션
# 에포크를 5회만 짧게 돌려 발산 현상이 초반에 어떻게 일어나는지 관찰함.
for epoch in range(1, 6):

    # [정상 신경망의 예측, 오차 계산, 가중치 수정 과정]
    out_good = w_good * x                           # 현재 가중치로 예측치를 도출함
    err_good = target - out_good                    # 오차를 계산함(정답 - 예측치)
    w_good = w_good + (lr_good * err_good * x)      # 적절한 학습률(0.2)을 곱하여 델타 규칙으로 가중치를 업데이트함

    # [과다 학습률 신경망의 예측, 오차 계산, 가중치 수정 과정]
    out_bad = w_bad * x                             # 문제 신경망의 예측치를 도출함
    err_bad = target - out_bad                      # 문제 신경망의 오차를 계산함
    w_bad = w_bad + (lr_bad * err_bad * x)          # 지나치게 큰 학습률(1.5)을 곱하여 델타 규칙으로 가중치를 무리하게 업데이트함

    # 매 에포크마다 두 신경망의 오차와 수정된 가중치 상태를 출력하여 직관적으로 비교함
    print(f"[epoch {epoch}]")
    print(f"  - 적정 학습률 (lr=0.2): 오차 {err_good:5.2f} -> 새 가중치 {w_good:6.2f} (안정적 접근)")
    print(f"  - 과다 학습률 (lr=1.5): 오차 {err_bad:5.2f} -> 새 가중치 {w_bad:6.2f} (지그재그 폭주!)")

print("\n-> 통찰: 학습률(보폭)이 너무 크면, 계곡 바닥을 지나쳐 반대편 언덕 더 높은 곳으로 튕겨 나가는 '오버슈팅'이 발생하여 영원히 정답을 찾지 못함.")
=== [실습 1-2] 학습률의 마법과 저주 ===
목표: 가중치(w)가 1.0에 도달해야 함.

[epoch 1]
  - 적정 학습률 (lr=0.2): 오차  0.90 -> 새 가중치   0.28 (안정적 접근)
  - 과다 학습률 (lr=1.5): 오차  0.90 -> 새 가중치   1.45 (지그재그 폭주!)
[epoch 2]
  - 적정 학습률 (lr=0.2): 오차  0.72 -> 새 가중치   0.42 (안정적 접근)
  - 과다 학습률 (lr=1.5): 오차 -0.45 -> 새 가중치   0.77 (지그재그 폭주!)
[epoch 3]
  - 적정 학습률 (lr=0.2): 오차  0.58 -> 새 가중치   0.54 (안정적 접근)
  - 과다 학습률 (lr=1.5): 오차  0.23 -> 새 가중치   1.11 (지그재그 폭주!)
[epoch 4]
  - 적정 학습률 (lr=0.2): 오차  0.46 -> 새 가중치   0.63 (안정적 접근)
  - 과다 학습률 (lr=1.5): 오차 -0.11 -> 새 가중치   0.94 (지그재그 폭주!)
[epoch 5]
  - 적정 학습률 (lr=0.2): 오차  0.37 -> 새 가중치   0.71 (안정적 접근)
  - 과다 학습률 (lr=1.5): 오차  0.06 -> 새 가중치   1.03 (지그재그 폭주!)

-> 통찰: 학습률(보폭)이 너무 크면, 계곡 바닥을 지나쳐 반대편 언덕 더 높은 곳으로 튕겨 나가는 '오버슈팅'이 발생하여 영원히 정답을 찾지 못함.

1.3. 5주차의 복수: 델타 규칙으로 파국적 간섭 완벽히 억제하기

  • 이론적 설명
    • 5주차 실습에서 사과([1, 1, -1, -1])와 토마토([1, 1, 1, -1])를 직교성(orthogonality) 없이 단순히 한 도화지에 덧셈(헵 규칙)했을 때, 두 과일이 공유하는 특징(빨갛다, 둥글다)의 가중치가 비정상적으로 누적(\(+3\), \(+4\))되어 시스템이 붕괴했음.
    • 하지만 델타 규칙은 오차를 줄이는 방향으로만 움직이므로, 이 ’비직교 패턴’들도 한 네트워크망 안에 잉크 번짐(폭주) 없이 안전하게 구별하여 저장할 수 있음.
  • 해결 원리(특징 선택 및 억제 메커니즘)
    • 네트워크에 사과를 보여주고 “이건 사과야(\(+1\))”라고 지도하고, 다음 날 토마토를 보여주고 “이건 토마토야(\(-1\))”라고 번갈아가며 오차를 튜닝함.
    • 학습이 반복되면 네트워크는 놀라운 사실을 스스로 깨달음: 빨갛다(1번 노드)와 둥글다(2번 노드)는 두 과일에 다 들어 있어서 정답을 맞히는 데 전혀 도움이 안 된다!
    • 델타 규칙은 오차를 최소화하기 위해 쓸모없는 공유 특징(1번, 2번 노드)의 시냅스 연결선 가중치를 스스로 아예 \(0\)에 가깝게 깎아버림(cancel out).
    • 대신 사과와 토마토를 완벽히 가르는 결정적 차이인 3번 노드(물렁함)의 가중치만 극대화시켜서 문제를 해결함.
  • 비유
    • Day 1: 사과 학습(목표 정답: \(+1\))
      • 사과를 보여줌. 사과의 특징은 [빨갛다, 둥글다]임.
      • 처음엔 신경망이 바보라서 \(0\)이라고 대답.
      • 정답은 \(+1\)인데 \(0\)이라고 했으니, 오차가 발생.
      • 가중치 튜닝: 델타 규칙에 따라 오차를 줄이기 위해 [빨갛다], [둥글다] 노드의 가중치를 살짝 올려줌(예: 각각 \(+0.1\)).
    • Day 2: 토마토 학습(목표 정답: \(-1\))
      • 다음 날 토마토를 보여줌. 토마토의 특징은 [빨갛다, 둥글다, 물렁하다]임.
      • 어제 사과를 배우면서 [빨갛다], [둥글다]\(+0.1\)로 올려놨기 때문에, 신경망은 토마토를 보고 “어? 이거 사과랑 비슷한데?”라며 \(+0.2\)라고 긍정적인 대답을 해버림.
      • 그런데 코치가 “아니야! 이건 토마토야(\(-1\))!”라고 혼냄. 엄청난 오차가 발생.
      • 가중치 튜닝: 오차를 줄이기 위해 이번엔 켜져 있던 [빨갛다], [둥글다], [물렁하다] 노드의 가중치를 크게 깎아내림(예: 각각 \(-0.2\)).
    • 수백 번 번갈아 반복 튜닝
      • 공통특징 [빨갛다, 둥글다]: 사과를 볼 때는 점수가 올라가고(\(+\)), 토마토를 볼 때는 점수가 깎임(\(-\)). 계속 더해졌다 빼지기를 반복하다 보니, 결국 이 노드들의 가중치는 \(0\)(쓸모없음)으로 수렴해버림.
      • 차이점 [물렁하다]: 사과를 볼 때는 이 특징이 아예 안 켜지니 아무 변화가 없지만, 토마토를 볼 때만 켜져서 계속 마이너스(\(-\)) 방향으로 깎임. 결국 이 노드의 가중치만 \(-1\)을 향해 강력하게 튜닝됨.
    • 오차의 튜닝: 사과와 토마토가 번갈아가며 만들어내는 오차(질책)를 피드백으로 삼아, 쓸모없는 공통점(빨강, 둥긂)의 가중치는 \(0\)으로 깎아내고 중요한 차이점(물렁함)의 가중치만 남기는 정밀한 영점조절 과정.

[실습 1-3] 델타 규칙을 통한 비직교 패턴의 간섭 억제 및 특징 추상화

  • 파국적 간섭을 일으켰던 두 패턴을 델타 규칙으로 학습시켜, 가중치가 떡지지 않고 깎여나가며 수렴하는지 확인.

[그림 8] [실습 1-3] 특징 선택: 비직교 패턴의 파국적 간섭 억제

Code
# 1. 5주차의 악몽: 특징이 심하게 겹치는 비직교 패턴 준비
# 4개의 감각 노드 구조: [빨강, 둥긂, 물렁함, 길쭉함]
# 사과는 빨갛고(+1), 둥글고(+1), 물렁하지 않으며(-1), 길쭉하지 않음(-1)
apple = np.array([1, 1, -1, -1])

# 토마토는 빨갛고(+1), 둥글고(+1), 물렁하며(+1), 길쭉하지 않음(-1)
tomato = np.array([1, 1,  1, -1])

# 정답(target) 세팅: 사과가 들어오면 +1을 출력하고, 토마토가 들어오면 -1을 출력하도록 지도학습 정답을 지시함.
target_apple = 1.0
target_tomato = -1.0

# 2. 가중치 초기화
# 4개의 감각특징을 받아들이기 위해 시냅스 연결 파이프 4개를 생성하고 가중치를 모두 0으로 비워둠.
# 벡터/행렬의 관례에 따라 W는 대문자로 유지함.
W = np.zeros(4)

# 가중치를 조금씩 수정할 학습률을 0.1로 안정적으로 설정함.
learning_rate = 0.1

print("=== [실습 1-3] 델타 규칙으로 파국적 간섭 억제 및 텐션 튜닝 ===")

# 3. 번갈아 가며 델타 규칙 학습(epoch 50회)
# 사과와 토마토를 한 번씩 번갈아 보여주는 과정을 50번 반복함.
for epoch in range(1, 51):

    # [사과 학습 단계]
    # 사과 데이터를 넣어 현재 뇌(W)가 사과를 얼마나 긍정적으로 판단하는지 예측함.
    out_apple = np.dot(W, apple)                 
    # 사과에 대한 이상적 정답(+1)에서 현재 예측치를 빼서 사과 오차를 계산함.
    err_apple = target_apple - out_apple         
    # 사과의 입력값, 오차, 학습률을 곱해 가중치를 양의 방향(+)으로 수정함.
    W = W + learning_rate * err_apple * apple    

    # [토마토 학습 단계]
    # 방금 수정된 뇌(W)에 토마토 데이터를 넣어 예측치를 산출함.
    out_tomato = np.dot(W, tomato)               
    # 토마토에 대한 이상적 정답(-1)에서 현재 예측치를 빼서 토마토 오차를 계산함.
    err_tomato = target_tomato - out_tomato      
    # 토마토의 입력값, 오차, 학습률을 곱해 가중치를 이번엔 음의 방향(-)으로 수정함.
    W = W + learning_rate * err_tomato * tomato  

    # 학습 과정을 10번마다 화면에 출력하여 총 오차가 점진적으로 0을 향해 수렴하는지 모니터링함.
    if epoch % 10 == 0:
        total_error = abs(err_apple) + abs(err_tomato)
        print(f"[epoch {epoch:2d}] 사과오차: {err_apple:5.2f} | 토마토오차: {err_tomato:5.2f} | 총오차: {total_error:5.2f}")

# 4. 폭주가 억제된 최종 가중치 맵 확인
# 반복학습이 끝난 후 최종적으로 결정된 시냅스 가중치 4개를 확인함.
print("\n[학습 완료] 최종 안정화된 가중치(W):", W.round(2))
print("-> 노드 1,2(빨강, 둥긂)와 노드 4(길쭉함)는 0으로 죽어버렸고, 노드 3(물렁함)만 -1로 강력하게 세팅됨!")

# 학습된 신경망이 사과와 토마토를 입력받았을 때 목표한 정답을 완벽히 뱉어내는지 검증함.
print("\n[검증 테스트]")
print(f"사과 입력 시 모델 출력: {np.dot(W, apple):.2f} (우리가 지시한 정답: {target_apple})")
print(f"토마토 입력 시 모델 출력: {np.dot(W, tomato):.2f} (우리가 지시한 정답: {target_tomato})")

print("\n-> 심화 해설: 5주차 헵 규칙에서는 1번, 2번 노드(빨강, 둥긂)가 계속 덧셈 누적되어 잉크가 떡지고 붕괴했음.")
print("-> 반면 델타 규칙은 두 과일을 구별하는 데 쓸모없는 공통 특징 가중치를 스스로 0으로 소거(cancel out)해버림.")
print("-> 오직 차이점인 3번 노드(물렁함) 하나만 잡고서 두 사물을 완벽하게 분류해내는 '데이터 추상화(abstraction)'의 지능을 획득함!")
=== [실습 1-3] 델타 규칙으로 파국적 간섭 억제 및 텐션 튜닝 ===
[epoch 10] 사과오차:  0.12 | 토마토오차: -0.11 | 총오차:  0.23
[epoch 20] 사과오차:  0.01 | 토마토오차: -0.01 | 총오차:  0.02
[epoch 30] 사과오차:  0.00 | 토마토오차: -0.00 | 총오차:  0.00
[epoch 40] 사과오차:  0.00 | 토마토오차: -0.00 | 총오차:  0.00
[epoch 50] 사과오차:  0.00 | 토마토오차: -0.00 | 총오차:  0.00

[학습 완료] 최종 안정화된 가중치(W): [-0. -0. -1.  0.]
-> 노드 1,2(빨강, 둥긂)와 노드 4(길쭉함)는 0으로 죽어버렸고, 노드 3(물렁함)만 -1로 강력하게 세팅됨!

[검증 테스트]
사과 입력 시 모델 출력: 1.00 (우리가 지시한 정답: 1.0)
토마토 입력 시 모델 출력: -1.00 (우리가 지시한 정답: -1.0)

-> 심화 해설: 5주차 헵 규칙에서는 1번, 2번 노드(빨강, 둥긂)가 계속 덧셈 누적되어 잉크가 떡지고 붕괴했음.
-> 반면 델타 규칙은 두 과일을 구별하는 데 쓸모없는 공통 특징 가중치를 스스로 0으로 소거(cancel out)해버림.
-> 오직 차이점인 3번 노드(물렁함) 하나만 잡고서 두 사물을 완벽하게 분류해내는 '데이터 추상화(abstraction)'의 지능을 획득함!

2부: 은닉층의 발견과 책임의 분배(오차 역전파)

2.1. 단층 퍼셉트론의 치명적 한계와 선형 분리 불가능성

  • 이론적 설명(단층구조의 기하학적 한계)
    • 델타 규칙으로 많은 최적화 문제가 해결되었으나, 1969년 마빈 민스키(Marvin Minsky)와 시모어 패퍼트(Seymour Papert)는 저서 Perceptrons를 통해 단층 퍼셉트론(입력층과 출력층만 있는 단순 구조)의 치명적인 수학적 한계를 완벽하게 증명함.
    • AND와 OR 연산의 성공
      • AND(둘 다 참일 때만 1)나 OR(하나라도 참이면 1) 문제는 2차원 평면(그래프)에 4개의 데이터를 찍었을 때, 단 하나의 일직선(선형경계, linear boundary)을 그어 정답(1)과 오답(0) 그룹을 깔끔하게 가를 수 있음(선형분리 가능).
      • 단층 퍼셉트론의 가중치 계산 수식(\(w_1x_1 + w_2x_2 + b = 0\))은 기하학적으로 볼 때 2차원 평면 위에 이 일직선 하나를 긋는 행위와 정확히 일치함.
    • XOR 문제(배타적 논리합)의 절망
      • 하지만 XOR 문제는 “두 입력이 서로 다를 때만 참(1)을, 같으면(둘 다 0이거나 둘 다 1) 거짓(0)을 반환하라”는 조건임.
      • 이를 2차원 평면에 점으로 찍으면 (0, 1)과 (1, 0)은 대각선으로 마주 보고, (0, 0)과 (1, 1) 역시 반대 대각선으로 마주 보는 교차 형태가 됨.
      • 아무리 가중치를 정교하게 튜닝(경사하강)해도, 평면 위에 빳빳한 직선 단 하나를 그어서 대각선으로 마주 보는 점들을 같은 그룹으로 묶어낼 방법은 우주상에 존재하지 않음 \(\Rightarrow\) 선형분리 불가능 문제.
  • 심화 해설(인지적 유연성의 부재와 맥락의 상실)
    • 4주차에서 깊이 논의했듯, 이 XOR 문제는 단순한 수학 논리 퍼즐이 아니라 고차원적 인간 인지의 필수요건인 맥락 의존성(context-dependency)을 상징하는 거대한 장벽임.
    • 예시
      • 인지 시스템에 “나는 커피(A)도 좋고, 오렌지 주스(B)도 좋지만, 두 개를 섞어 마시는 것(A AND B)은 최악이다”라는 취향을 학습시킨다고 가정해보겠음.
      • 단층 퍼셉트론은 단순히 입력된 신호의 호감도(가중치)를 ‘독립적으로 더하는(덧셈)’ 역할만 하므로, 커피(+1)와 주스(+1)가 동시에 들어오면 긍정 수치가 폭발하여 무조건 ’아주 좋다(+2)’는 치명적인 오답 결론을 내림.
    • 이처럼 단층 구조의 선형적 판단력으로는 “각각의 요소는 긍정적이지만, 두 요소가 ‘동시에’ 존재할 때는 부정적으로 의미가 뒤집힌다”는 비선형적이고 배타적인 상호작용(맥락)을 절대 분리해낼 수 없음. 결국 이 단순한 1차원적 덧셈 기계는 조금만 맥락이 꼬여 있는 환경을 만나면 영원히 에러율 50%의 늪에 빠져 허우적대며, 인공지능 역사에 길고 추운 첫 번째 AI 겨울을 불러오게 됨.

[그림 9] 선형 분리 불가능성: 1차원적 덧셈 기계의 절망

[실습 2-1] 파이썬으로 확인하는 단층 퍼셉트론의 선형 분리 한계(XOR 실패 목격)

  • 수만 번을 델타 규칙으로 학습시켜도, 은닉층이 없는 단층 모델은 XOR 문제에서 오차를 줄이지 못하고 절망적인 0.5 근처를 맴돌게 됨을 직접 목격.

[그림 10] [실습 2-1] 파이썬으로 목격하는 평면의 한계

Code
import numpy as np

# 1. XOR 데이터셋 준비
# XOR 논리 회로: 두 입력이 [0,0]이거나 [1,1]로 같으면 정답은 0, 서로 다르면([0,1] 또는 [1,0]) 정답은 1을 출력해야 함.
X_xor = np.array([[0,0], [0,1], [1,0], [1,1]])
Y_xor = np.array([[0],   [1],   [1],   [0]])

# 2. 단층 퍼셉트론 가중치 세팅
# 은닉층 없이 입력 2개에서 곧바로 출력 1개로 직행하는 2 x 1 가중치 행렬을 임의로(0.1, 0.2) 생성함.
W_single = np.array([[0.1], [0.2]])
learning_rate = 0.1

print("=== [실습 2-1] 단층 퍼셉트론의 절망: XOR 문제 시도 ===")

# 3. 5000번의 고된 델타 규칙 훈련
# 직선(선형 모델)으로 대각선 데이터를 자르기 위해 무려 5,000번이나 오차를 수정함.
for epoch in range(5000):

    # 입력 데이터 4세트 전체를 한꺼번에 가중치와 내적 곱셈(선형 변환) 처리함.
    linear_out = np.dot(X_xor, W_single)

    # 선형 합산된 값을 시그모이드 함수에 통과시켜 모든 값을 0과 1 사이로 부드럽게 압축함(확률값 도출).
    output = 1 / (1 + np.exp(-linear_out)) 

    # 각각의 정답에서 현재의 압축된 예측치를 빼서 전체 에러를 계산함.
    error = Y_xor - output

    # 시그모이드를 쓴 비선형 단층 퍼셉트론의 델타 규칙 가중치 수정 공식을 적용함.
    # error에 시그모이드 미분값인 output*(1-output)을 곱한 뒤 입력 행렬의 전치(X.T)를 곱해 기울기를 구함.
    delta_w = learning_rate * np.dot(X_xor.T, error * output * (1 - output))

    # 계산된 변화량만큼 단층 가중치를 업데이트함.
    W_single += delta_w


# 4. 최종 예측 결과 확인
print("\n[학습 완료] 단층 퍼셉트론의 XOR 예측 결과:")

# 5,000번 훈련이 끝난 최종 가중치(W_single)를 사용하여 4가지 입력 패턴의 결과를 최종 산출함.
final_prediction = 1 / (1 + np.exp(-np.dot(X_xor, W_single)))

# 4개의 입력 셋트를 루프로 돌면서 정답과 딥러닝 모델의 예측값을 나란히 출력하여 비교함.
for i in range(4):
    print(f"입력: {X_xor[i]} -> 예측: {final_prediction[i][0]:.4f} (정답: {Y_xor[i][0]})")

print("\n-> 심화 해설: 5000번이나 학습시켰지만, 예측값이 모두 0.5 언저리로 붕괴해버림.")
print("-> 직선 하나로는 대각선 데이터를 가를 수 없기 때문에, 신경망이 '모르겠다(0.5)'라고 포기해버린 수학적 절망 상태를 보여줌.")
=== [실습 2-1] 단층 퍼셉트론의 절망: XOR 문제 시도 ===

[학습 완료] 단층 퍼셉트론의 XOR 예측 결과:
입력: [0 0] -> 예측: 0.5000 (정답: 0)
입력: [0 1] -> 예측: 0.5000 (정답: 1)
입력: [1 0] -> 예측: 0.5000 (정답: 1)
입력: [1 1] -> 예측: 0.5000 (정답: 0)

-> 심화 해설: 5000번이나 학습시켰지만, 예측값이 모두 0.5 언저리로 붕괴해버림.
-> 직선 하나로는 대각선 데이터를 가를 수 없기 때문에, 신경망이 '모르겠다(0.5)'라고 포기해버린 수학적 절망 상태를 보여줌.

2.2. 오차 역전파(backpropagation): 책임은 누구에게 있는가?

  • 이론적 설명(기여도 할당의 딜레마)
    • 단층 퍼셉트론의 한계를 부수기 위한 해결책은 명확했음. 입력층과 출력층 사이에 은닉층이라는 새로운 중간 다리를 놓아 다층 퍼셉트론(multi-layer perceptron, MLP) 구조를 만드는 것임.
    • 그러나 다층 구조가 되면서 인지과학과 AI 모두에 거대한 딜레마가 발생함. 바로 기여도 할당 문제(credit assignment problem)임.
    • 최종 출력층(운동신경)에서 오차가 발생했을 때, 이 오차의 책임은 바로 앞단인 [은닉층 \(\rightarrow\) 출력층을 잇는 가중치(\(W_2\))]에 있는가? 아니면 아예 처음부터 데이터가 잘못 넘어온 [입력층 \(\rightarrow\) 은닉층을 잇는 가중치(\(W_1\))]에서부터 꼬인 것인가?
    • 외부에서 정답(target)을 직접 알려주는 곳은 오직 최종 출력층뿐임. 그렇다면 정답을 알 수 없는 중간 기착지, 즉 [입력층 \(\rightarrow\) 은닉층을 잇는 가중치(\(W_1\))]는 도대체 자신의 오차를 어떻게 구해서 델타 규칙을 적용한단 말인가?

[그림 11] 다층 구조의 등장과 기여도 할당의 딜레마

  • 해결책: 미분의 연쇄법칙
    • 1980년대 제프리 힌튼(Geoffrey Hinton), 데이비드 루멜하트(David Rumelhart) 등이 제안한 오차 역전파 알고리즘이 10여 년의 AI 겨울을 끝내고 이 문제를 해결함.
    • 고등학교 수학에 나오는 미분의 ’연쇄법칙(합성함수의 미분)’을 이용해, 최종 출력층에서 계산된 오차(\(\delta\))를 뒤에서부터 앞으로(backward) 가중치 파이프라인을 거꾸로 타고 흘려보내며 각 시냅스 다리(\(W_2\), \(W_1\))의 책임 비율을 분배함.

[그림 12] 사장님의 분노와 미분의 연쇄법칙

  • 비유(회사 조직의 적자와 내리갈굼)
    • 구조
      • 입력층 = 말단 사원.
      • 은닉층 = 중간 관리자.
      • 출력층 = 사장.
      • 손실(error) = 회사의 막대한 적자.
    • 가중치 다리
      • \(W_1\) = 말단 사원의 보고를 중간 관리자가 신뢰하는 정도.
      • \(W_2\) = 중간 관리자의 기획안을 사장이 신뢰하는 정도.
    • 순전파(forward pass): 말단 사원이 원본 데이터를 올리면(\(W_1\) 통과), 중간 관리자가 취합하고, 사장이 최종 결정함(\(W_2\) 통과). \(\rightarrow\) 결재가 났는데 회사가 10억 적자를 봄.
    • 역전파(backward pass):
      • 적자(오차)가 발생하면, 사장은 중간 관리자가 적자에 기여한 지분(기울기)을 따져 묻고, 그 책임만큼 중간 관리자에 대한 신뢰도(가중치 \(W_2\))를 깎아버림.
      • 질책을 받은 중간 관리자는 자기가 받은 벌점을 바탕으로, 애초에 데이터를 올린 말단 사원들의 책임 지분을 역추적하여 그들에 대한 신뢰도(가중치 \(W_1\))를 깎아내림.
      • 요약: 이처럼 “정확한 책임 비율(오차)을 위에서 아래로 연쇄적으로 따져 묻고, 그 벌점만큼 서로 간의 신뢰도(가중치)를 수정하는” 구조가 역전파 알고리즘의 핵심임.

[그림 13] 오차 역전파: 책임의 연쇄 추궁

[실습 2-2] 다층 신경망의 순전파와 역전파 1회차 해부하기

  • 복잡한 미분 수식 대신, 파이썬 행렬 연산을 통해 오차가 뒷단에서 앞단으로 어떻게 거꾸로 흘러 들어가는지 코드의 흐름(chain rule)을 뜯어봄.
  • “전치행렬”과 W2.T란?
    • 전치행렬(transpose matrix): 행렬의 행(가로)열(세로)을 서로 맞바꾼 행렬을 뜻함. 수학기호로는 행렬 우측 상단에 알파벳 \(T\)를 붙여서 \(W^T\)라고 표기. 세로로 길쭉했던 행렬은 가로로 눕혀지고, 가로로 넓었던 행렬은 세로로 세워지는 연산.
    • W2.T의 의미: 파이썬의 numpy 라이브러리에서는 행렬 변수 뒤에 .T만 붙이면 전치행렬을 만들어줌. 즉 W2.T“W2 행렬의 가로세로 방향을 뒤집어라”라는 파이썬 명령어.
  • 왜 역전파에서 ’전치’가 필수적인가?
    • [실습 2-2]의 뼈대를 보면 중간 관리자(은닉층)는 2명이고, 사장님(출력층)은 1명임.
    • 순전파(업무보고 방향): \(W_2\) 사용
      • 보고서는 2명(은닉층) \(\rightarrow\) 1명(출력층) 방향으로 올라감.
      • 이때 두 층을 연결하는 가중치 파이프 \(W_2\)는 중간 관리자 각각의 신뢰도를 담아야 하므로 [[0.6], [0.7]]이라는 2행 1열(세로로 긴 모양)의 행렬이 됨.
    • 역전파(내리갈굼 방향): \(W_2^T\) 사용
      • 회사가 적자(오차)를 보면, 이제 사장님이 중간 관리자들에게 책임을 물어야 함.
      • 질책의 방향은 아까와 반대로 1명(출력층) \(\rightarrow\) 2명(은닉층) 방향으로 ’역류’해야 함.
      • 방향이 거꾸로 바뀌었기 때문에, 보고서가 올라갈 때 썼던 세로 파이프(\(W_2\), 2x1)를 그대로 쓸 수가 없음. 수학적으로 행렬의 아귀(차원)가 맞지 않기 때문.
      • 그래서 사장님의 질책(\(\Delta\)) 1개가 2명의 중간 관리자에게 쫙 퍼져 내려가도록, 기존 파이프를 가로로 눕혀서 1행 2열([0.6, 0.7])(수학적으로는 전치를 해도 여전히 행렬이지만, 파이썬 상에서는 벡터로 취급됨)의 파이프로 억지로 방향을 뒤집어주는 작업이 필요. 이것이 바로 전치행렬(W2.T)을 곱하는 이유.

[그림 14] [실습 2-2] 행렬의 전치(Transpose)와 역류하는 파이프

Code
# 0. 사전 함수 정의
# 어떤 값이든 0과 1 사이로 압축해주는 비선형 활성화 함수인 시그모이드 함수를 정의함.
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# 신경망의 곡선 기울기(미분)를 구하는 함수. 시그모이드는 (결과값) * (1 - 결과값)으로 매우 간단히 미분됨.
def sigmoid_derivative(out):
    return out * (1 - out)

# 1. 네트워크 뼈대 구성
# 입력 노드 2개(말단 사원 2명)가 제출한 데이터 보고서를 세팅함.
X = np.array([[1.0, 0.5]])

# 최종 출력 노드 1개(사장님)가 기대한 완벽한 100% 이익(정답)을 세팅함.
target = np.array([[1.0]])

# 2. 가중치 초기화
# 말단 사원(2명)에서 중간 관리자(2명)로 가는 W1 파이프(2x2 행렬)의 호감도를 양수로 고정 세팅함.
W1 = np.array([[0.2, 0.3],
               [0.4, 0.5]])

# 중간 관리자(2명)에서 사장님(1명)으로 가는 W2 파이프(2x1 행렬)의 호감도를 세팅함.
W2 = np.array([[0.6],
               [0.7]])

# 한 번 혼낼 때마다 가중치를 얼마나 깎을지 결정할 학습률을 0.5로 크게 설정함.
learning_rate = 0.5

print("=== [실습 2-2] 오차 역전파 흐름 1회차 뜯어보기 ===")

# --------------------------------------------------------
# [Step 1] 순전파(forward pass): 입력 -> 은닉 -> 출력(업무보고 라인)
# --------------------------------------------------------
# 입력 데이터가 W1 가중치 망을 통과하여 은닉층에 도착한 순수 전기 합산량을 구함.
hidden_input = np.dot(X, W1)

# 은닉층 노드가 그 합산량을 시그모이드 함수로 압축시켜 내부 표상(중간 결재안)을 생성함.
hidden_out = sigmoid(hidden_input)

# 은닉층의 결과물이 W2 가중치 망을 통과하여 최종 출력층(사장님)에 도달한 합산량을 구함.
final_input = np.dot(hidden_out, W2)

# 사장님이 그 합산량을 시그모이드 함수로 압축시켜 최종 예측(회사 실적)을 뱉어냄.
final_out = sigmoid(final_input)

# 사장님이 기대한 정답(target)에서 방금 도출한 최종 실적(final_out)을 빼서 발생한 적자(총 오차)를 구함.
error = target - final_out

# 업무 보고가 끝나고 1차적으로 발생한 오차가 얼마인지 화면에 출력함.
print(f"1. 사장님 최종 예측: {final_out[0][0]:.4f} | 타겟: {target[0][0]:.4f} | 발생한 오차: {error[0][0]:.4f}")

# --------------------------------------------------------
# [Step 2] 역전파 1단계: 출력층 -> 은닉층 가중치(W2) 책임 묻기
# --------------------------------------------------------
# 사장님 층의 국소 오차(델타) = 총 발생한 오차 * 사장님 층의 곡선 기울기(시그모이드 미분값).
d_output = error * sigmoid_derivative(final_out)

# 델타 규칙: (은닉층 출력물의 전치 행렬) * (사장층 델타) * (학습률)을 통해 W2를 얼마나 고칠지 양을 계산함.
delta_w2 = learning_rate * np.dot(hidden_out.T, d_output)

# W2 가중치 파이프가 얼마나 두꺼워지거나 깎여나가야 하는지 화면에 출력함.
print(f"2. 중간관리자와 사장 사이의 가중치(W2) 업데이트량:\n{delta_w2.round(4)}")

# --------------------------------------------------------
# [Step 3] 역전파 2단계: 은닉층 -> 입력층 가중치(W1) 책임 묻기 (내리갈굼의 핵심)
# --------------------------------------------------------
# [가장 중요한 연쇄법칙 단계] 은닉층은 자신만의 정답이 없으므로, 방금 구한 사장층의 델타(d_output)를
# 기존의 W2 파이프(전치행렬 형태)를 타고 '거꾸로(역류)' 내려보내 중간 관리자들의 순수 책임량을 추산함.
error_hidden = np.dot(d_output, W2.T)

# 역류해 들어온 은닉층의 에러 합산량에 자신의 곡선 기울기(시그모이드 미분값)를 곱해 은닉층의 진짜 국소 오차(델타)를 완성함.
d_hidden = error_hidden * sigmoid_derivative(hidden_out)

# 델타 규칙: (원래 입력물의 전치 행렬) * (은닉층 델타) * (학습률)을 통해 W1 가중치를 어떻게 고칠지 양을 계산함.
delta_w1 = learning_rate * np.dot(X.T, d_hidden)

# W1 가중치가 어떻게 업데이트되어야 하는지 최종적으로 화면에 출력함.
print(f"3. 말단사원과 중간관리자 사이의 가중치(W1) 업데이트량 (오차 역류의 결과):\n{delta_w1.round(4)}")
print("\n-> 통찰: 은닉층 가중치(W1)는 밖에서 주어지는 오차 정답을 몰라도, 오차 역전파를 통해 W2를 거쳐 역류해 들어온 수학적 책임(d_hidden)을 받아 스스로를 수정할 수 있음!")
=== [실습 2-2] 오차 역전파 흐름 1회차 뜯어보기 ===
1. 사장님 최종 예측: 0.6906 | 타겟: 1.0000 | 발생한 오차: 0.3094
2. 중간관리자와 사장 사이의 가중치(W2) 업데이트량:
[[0.0198]
 [0.021 ]]
3. 말단사원과 중간관리자 사이의 가중치(W1) 업데이트량 (오차 역류의 결과):
[[0.0048 0.0054]
 [0.0024 0.0027]]

-> 통찰: 은닉층 가중치(W1)는 밖에서 주어지는 오차 정답을 몰라도, 오차 역전파를 통해 W2를 거쳐 역류해 들어온 수학적 책임(d_hidden)을 받아 스스로를 수정할 수 있음!

2.3. 은닉층의 비선형적 공간 왜곡과 XOR의 정복

  • 이론적 설명(은닉층의 역할과 공간 왜곡)
    • 단층 퍼셉트론이 데이터를 가르기 위해 빳빳한 직선 하나만 그을 수 있다면, 은닉층과 비선형 활성화 함수(sigmoid 등)가 결합된 다층구조는 데이터가 놓인 차원의 뼈대 자체를 구부러뜨리고 왜곡하는 강력한 능력을 가짐.
    • 오차 역전파는 단순히 결과의 정답을 맞히는 것을 넘어, 이 공간을 ‘어떻게 구부려야’ 꼬여 있는 데이터를 가장 잘 가를 수 있는지 은닉층 뉴런들에게 그 기준을 수학적으로 학습시킴.
  • 심화 해설(내부 표상과 고차원 분리)
    • 인지과학적으로 은닉층을 통과한다는 것은 망막에 맺힌 날것의 2차원 감각 데이터(XOR)를 뇌가 이해하기 쉬운 고차원적 개념으로 재배치하여 내부 표상(internal representation)을 형성하는 과정임.
    • 2차원 평면에 대각선으로 얽혀있던 평범한 XOR 데이터는, 은닉층 노드들(hidden nodes)이 각자의 가중치 기준에 맞게 이리저리 당기고 휘게 만들면서 3차원 이상의 구부러진 언덕으로 재배치됨.
    • 데이터가 3차원 입체로 구부러지면, 그 구부러진 골짜기 사이로 평평한 색종이(선형평면[hyperplane])를 쑥 집어넣어 데이터를 두 그룹으로 완벽하게 잘라낼 수 있음. 이것이 은닉층이 지닌 비선형성 마법의 본질임.
  • 비유(종이 접기와 한 번의 가위질)
    • 종이 접기 비유: 검은 점 2개와 흰 점 2개가 대각선 모양으로 엇갈려 그려져 있는 평평한 도화지(XOR 데이터)가 있음. 이 도화지를 바닥에 그대로 둔 채, 자를 대고 직선으로 단 한 번 가위질(단층 퍼셉트론)을 해서 검은 점과 흰 점을 나눌 방법은 절대 없음.
    • 하지만 도화지를 허공으로 들어 올려 입체적으로 둥글게 접거나 꼬아버리면(은닉층의 비선형 왜곡), 엇갈려 있던 검은 점들과 흰 점들의 ’높이(차원)’가 달라지게 됨.
    • 이렇게 2차원 종이를 3차원 입체로 비틀어버리면, 허공에서 단 한 번의 평평한 가위질(최종 출력층의 선형 경계)만으로도 두 집단을 완벽하게 잘라낼 수 있음.

[그림 15] 은닉층의 본질: 비선형적 공간 왜곡

[실습 2-3] 다층 신경망(MLP)의 10,000번 역전파 루프와 XOR 문제 정복

  • [실습 2-1]에서 단층 퍼셉트론이 절대 풀지 못했던 XOR 데이터셋을, 방금 만든 2층짜리 다층 신경망(MLP)과 역전파 루프에 넣어 10,000번 훈련시켜 완벽히 풀어낼 수 있음.

[그림 16] [실습 2-3] 다층 신경망(MLP)의 공간 왜곡과 XOR 정복

Code
# 1. 풀리지 않던 XOR 데이터셋 재준비
# 입력 4종류와 이에 매칭되는 정답 4종류를 배열로 정의함.
X_xor = np.array([[0,0], [0,1], [1,0], [1,1]])
Y_xor = np.array([[0],   [1],   [1],   [0]])

# 2. 다층 신경망 (2입력 -> 4은닉 -> 1출력) 뼈대 세팅
# 동일한 결과를 재현하기 위해 파이썬 난수 생성기의 시드(씨앗) 값을 42로 고정함.
np.random.seed(42)

# 입력층(2개)에서 은닉층(4개)으로 가는 W1 행렬을 생성하고, -1에서 1 사이의 난수로 무작위 초기화함.
# 은닉 노드를 4개로 넉넉히 두어 2차원 평면을 고차원 입체로 충분히 비틀어 휘게 만듦.
W1 = np.random.uniform(-1, 1, (2, 4))

# 은닉층(4개)에서 출력층(1개)으로 가는 W2 가중치 파이프 4개를 난수로 초기화함.
W2 = np.random.uniform(-1, 1, (4, 1))

# 오차 역전파 시 가중치를 한 번에 크게 수정하여 빠르게 학습시키기 위해 학습률을 1.0으로 대폭 키움.
learning_rate = 1.0

print("=== [실습 2-3] 오차 역전파를 이용한 XOR 문제의 완벽한 정복 ===")

# 3. 10,000번의 순전파와 역전파 무한 루프 반복 훈련
for epoch in range(10000):

    # [순전파 단계]
    # 전체 입력 데이터(X_xor)를 은닉층(W1)으로 보내 시그모이드 비선형 함수로 압축 및 왜곡(내부 표상)시킴.
    hidden_out = sigmoid(np.dot(X_xor, W1))

    # 왜곡된 은닉층 데이터를 출력층(W2)으로 보내 최종 딥러닝 예측값(final_out)을 도출함.
    final_out = sigmoid(np.dot(hidden_out, W2))

    # [오차 계산 단계]
    # 최종 예측값이 정답(Y_xor)에서 얼마나 벗어났는지 모든 데이터 셋에 대해 오차 행렬을 계산함.
    error = Y_xor - final_out

    # [역전파 단계: 연쇄 법칙]
    # 출력층 사장님의 델타(국소 오차)를 미분 기울기를 곱해 계산함.
    d_output = error * sigmoid_derivative(final_out)

    # 사장님의 델타(d_output)를 W2 파이프를 타고 역류시킨 뒤, 은닉층 자체의 미분 기울기를 곱해 은닉층의 델타를 도출함.
    d_hidden = np.dot(d_output, W2.T) * sigmoid_derivative(hidden_out)

    # [가중치 업데이트 단계]
    # 계산된 사장층 델타에 학습률과 은닉층 출력 정보를 곱해 출력층 앞 가중치(W2)를 수정 누적함.
    W2 += learning_rate * np.dot(hidden_out.T, d_output)

    # 계산된 은닉층 델타에 학습률과 입력 정보를 곱해 말단-은닉 사이의 가중치(W1)를 수정 누적함.
    W1 += learning_rate * np.dot(X_xor.T, d_hidden)

    # 2000번 루프가 돌 때마다 현재의 전체 신경망이 손실 공간에서 얼마나 바닥(0)으로 내려왔는지 
    # '오차 제곱의 평균(MSE loss)'을 화면에 출력하여 모니터링함.
    if epoch % 2000 == 0:
        loss = np.mean(np.square(error))
        print(f"[epoch {epoch:4d}] loss: {loss:.4f} (손실 공간을 타고 밑바닥으로 수렴 중...)")

# 4. 학습 완료 후 최종 딥러닝 예측 결과 검증
print("\n[학습 완료] XOR 예측 결과 테스트:")

# 만 번의 훈련을 마치고 완벽히 조율된 W1과 W2를 사용해 마지막으로 전체 입력값에 대한 예측을 한 번 더 수행함.
final_prediction = sigmoid(np.dot(sigmoid(np.dot(X_xor, W1)), W2))

# 각 입력 패턴에 대해 모델이 출력한 예측값이 0 또는 1의 정답과 얼마나 가까워졌는지 출력함.
for i in range(4):
    print(f"입력: {X_xor[i]} -> 딥러닝 예측: {final_prediction[i][0]:.4f} (정답: {Y_xor[i][0]})")

print("\n-> 최종 결론: 단층 모델로는 0.5에서 계속 멈추던 XOR 문제를, 은닉층을 통한 '비선형 공간 왜곡'과 역전파의 '미분 책임 배분'을 통해 완벽하게(0과 1에 극도로 수렴하게) 풀어냄!")
print("-> 이것이 오늘날 모든 딥러닝 모델과 뇌 과학 연결주의 아키텍처를 작동시키는 근본 동력임.")
=== [실습 2-3] 오차 역전파를 이용한 XOR 문제의 완벽한 정복 ===
[epoch    0] loss: 0.2629 (손실 공간을 타고 밑바닥으로 수렴 중...)
[epoch 2000] loss: 0.0016 (손실 공간을 타고 밑바닥으로 수렴 중...)
[epoch 4000] loss: 0.0007 (손실 공간을 타고 밑바닥으로 수렴 중...)
[epoch 6000] loss: 0.0004 (손실 공간을 타고 밑바닥으로 수렴 중...)
[epoch 8000] loss: 0.0003 (손실 공간을 타고 밑바닥으로 수렴 중...)

[학습 완료] XOR 예측 결과 테스트:
입력: [0 0] -> 딥러닝 예측: 0.0187 (정답: 0)
입력: [0 1] -> 딥러닝 예측: 0.9894 (정답: 1)
입력: [1 0] -> 딥러닝 예측: 0.9829 (정답: 1)
입력: [1 1] -> 딥러닝 예측: 0.0142 (정답: 0)

-> 최종 결론: 단층 모델로는 0.5에서 계속 멈추던 XOR 문제를, 은닉층을 통한 '비선형 공간 왜곡'과 역전파의 '미분 책임 배분'을 통해 완벽하게(0과 1에 극도로 수렴하게) 풀어냄!
-> 이것이 오늘날 모든 딥러닝 모델과 뇌 과학 연결주의 아키텍처를 작동시키는 근본 동력임.

6주차 요약 및 다음 주 예고

[그림 17] 패러다임 비교: 선형적 덧셈에서 차원의 조작으로

  • 요약
    • 인지 시스템은 단순한 동시성 덧셈(헵 규칙)만으로는 복잡한 간섭현상을 통제할 수 없음.
    • 레스콜라-와그너 모델이 시사하듯, 뇌는 예측오차를 계산하여 가중치를 미분적으로 깎아내는 델타 규칙(경사하강법)을 사용함.
    • 역전파 알고리즘
      • 다층구조에서 최종오차의 책임을 ’데이터를 기초 가공하는 은닉층(중간 관리자)’으로 거꾸로 전달함.
      • 연결주의 모델이 직선적 사고의 한계를 넘어, 공간을 왜곡하고 복잡한 문제를 해결할 수 있게 만든 결정적인 수학적 엔진임.
  • 다음 주(7주차) 예고
    • 시냅스 가중치가 충분히 훈련된 이후, 뇌는 외부에서 쏟아지는 불확실한 감각정보(증거)들을 초당 단위로 어떻게 긁어모아 최종적인 의사결정을 내리는가?
    • 이 과정에서 왜 어려운 문제는 반응시간(RT)이 오래 걸리는지, ‘빠른 결정(속도)’과 ’신중한 결정(정확성)’ 사이의 타협(trade-off) 메커니즘을 확률적인 그래프로 시뮬레이션하는 표류확산 모델(drift diffusion model, DDM)을 다룰 예정임.

[그림 18] 넥스트 스텝: 증거 축적과 의사결정의 시간