5차시: 다층 신경망 - TensorFlow Playground로 XOR 정복하기
🎯 이 차시의 핵심 주제
섹션 제목: “🎯 이 차시의 핵심 주제”🧠 은닉층의 마법
섹션 제목: “🧠 은닉층의 마법”뉴런을 여러 층으로 쌓으면 왜 곡선 경계가 만들어지는지 이해합니다
🔧 Playground 실험
섹션 제목: “🔧 Playground 실험”TensorFlow Playground에서 층과 뉴런을 바꿔가며 XOR·원형·나선형 데이터를 분류합니다
💻 Keras 코드 구현
섹션 제목: “💻 Keras 코드 구현”Dense 두 줄로 XOR을 학습시키는 신경망을 직접 작성합니다
📝 정리와 성찰
섹션 제목: “📝 정리와 성찰”시뮬레이터 조작과 코드 한 줄을 연결해 “무엇이 학습되었는지” 설명합니다
⏱️ 수업 흐름
섹션 제목: “⏱️ 수업 흐름”1단계: 복습과 문제 제기 (10분)
섹션 제목: “1단계: 복습과 문제 제기 (10분)”지난 시간 단층 퍼셉트론이 XOR에서 실패한 이유를 5분 복습합니다. 종이에 직선 하나로 XOR 네 점을 분리해 보며 “직선이 부족하다”는 체험을 공유합니다.
2단계: Playground로 XOR 정복 (25분)
섹션 제목: “2단계: Playground로 XOR 정복 (25분)”TensorFlow Playground에 접속해 XOR 데이터를 불러오고, 은닉층 1개·뉴런 2-4개로 학습을 돌립니다. 결정 경계가 곡선으로 휘는 과정을 관찰하고, 각 뉴런의 작은 그림을 해석합니다.
3단계: 층 수와 뉴런 수 실험 (15분)
섹션 제목: “3단계: 층 수와 뉴런 수 실험 (15분)”원형·나선형 데이터셋에서 층 수와 뉴런 수를 바꿔가며 언제 학습이 되고 언제 실패하는지 기록합니다. 모둠별 실험 결과를 표로 정리합니다.
4단계: Keras로 코드 구현 (25분)
섹션 제목: “4단계: Keras로 코드 구현 (25분)”Colab에서 Keras Sequential API로 Dense 2층 신경망을 만들어 XOR을 학습시킵니다. v1 단층 실패 → v2 은닉층 추가 → v3 활성화 함수 변경 순으로 진화시킵니다.
5단계: 정리와 형성평가 (5분)
섹션 제목: “5단계: 정리와 형성평가 (5분)”오늘의 질문에 스스로 답하고, 형성평가 2문항을 풉니다. 다음 차시(역전파) 예고로 마무리합니다.
📚 핵심 개념
섹션 제목: “📚 핵심 개념”개념 1. 왜 직선 하나로는 XOR을 풀 수 없는가
섹션 제목: “개념 1. 왜 직선 하나로는 XOR을 풀 수 없는가”4차시 끝에서 만났던 XOR 데이터를 다시 떠올려 보겠습니다. 입력이 (0,0)과 (1,1)이면 출력은 0, (0,1)과 (1,0)이면 출력은 1입니다. 이 네 점을 평면에 찍으면 같은 클래스가 대각선 방향으로 놓입니다. 아무리 자를 기울여 봐도 직선 하나로는 0과 1을 가를 수 없습니다.
이 한계는 수학적으로 분명합니다. 단층 퍼셉트론의 결정 경계는 식 (1)과 같이 하나의 직선이기 때문입니다.
$ w_1 x_1 + w_2 x_2 + b = 0 \tag{1} $
여기서 $w_1, w_2$는 가중치, $b$는 편향입니다. 이 식은 평면에서 직선 하나만 그립니다. XOR처럼 선형 분리 불가능(linearly non-separable)한 데이터에는 근본적으로 맞지 않습니다.
해결 방법은 간단합니다. 자를 두 개 쓰면 됩니다. 자 하나로 “x₁이 크면 1”을 긋고, 다른 자로 “x₂가 크면 1”을 그은 다음, 두 결과를 똑똑하게 조합하면 XOR을 풀 수 있습니다. 이 “두 자를 조합하는 방”이 바로 은닉층입니다.
개념 2. 은닉층: 공간을 휘게 만드는 층
섹션 제목: “개념 2. 은닉층: 공간을 휘게 만드는 층”은닉층은 입력을 받아 새로운 특성(feature)으로 변환합니다. 사진 보정 앱에서 원본 사진에 “밝기 필터”, “대비 필터”를 각각 적용한 뒤, 두 결과를 합쳐 새로운 사진을 만드는 것과 비슷합니다. 은닉층의 각 뉴런은 서로 다른 관점으로 입력을 바라보는 “필터”입니다.
정의를 분명히 하겠습니다. 은닉층은 입력층과 출력층 사이에 위치하며, 입력 벡터 $\mathbf{x}$를 비선형 함수로 변환해 다음 층에 전달하는 층입니다. 2층 신경망의 계산은 식 (2)와 같습니다.
$ \begin{aligned} \mathbf{h} &= \sigma(\mathbf{W}_1 \mathbf{x} + \mathbf{b}_1) \ \hat{y} &= \sigma(\mathbf{W}_2 \mathbf{h} + \mathbf{b}_2) \end{aligned} \tag{2} $
첫 줄에서 입력 $\mathbf{x}$가 은닉 벡터 $\mathbf{h}$로 변환되고, 둘째 줄에서 $\mathbf{h}$가 최종 예측 $\hat{y}$로 변환됩니다. $\sigma$는 활성화 함수(ReLU나 시그모이드 등)로, 이것이 없으면 아무리 층을 쌓아도 직선 하나와 같습니다.
flowchart LR
X1([x1]) --> H1[뉴런 1<br/>필터 A]
X1 --> H2[뉴런 2<br/>필터 B]
X2([x2]) --> H1
X2 --> H2
H1 --> Y[출력<br/>조합]
H2 --> Y
Y --> P([예측])
은닉층 뉴런 2개가 서로 다른 직선을 그리고, 출력층이 그 둘을 조합해 곡선 경계를 만드는 구조입니다.
개념 3. 활성화 함수: 비선형성의 원천
섹션 제목: “개념 3. 활성화 함수: 비선형성의 원천”활성화 함수가 왜 필요한지는 간단한 논리로 알 수 있습니다. 활성화 함수 없이 층을 두 개 쌓으면 $\mathbf{W}_2(\mathbf{W}_1 \mathbf{x}) = (\mathbf{W}_2 \mathbf{W}_1)\mathbf{x}$가 되어, 결국 하나의 직선과 다를 바 없습니다. 층을 아무리 쌓아도 소용이 없습니다. 중간에 구부림을 넣어야 공간이 휘어집니다.
대표적인 활성화 함수 세 가지를 비교하겠습니다.
| 이름 | 수식 | 특징 | 주 용도 |
|---|---|---|---|
| 시그모이드 | $\sigma(z) = \dfrac{1}{1+e^{-z}}$ | 0-1 사이 부드러운 S자 | 이진 분류 출력층 |
| tanh | $\tanh(z)$ | -1과 1 사이 S자 | 은닉층(옛날 방식) |
| ReLU | $\max(0, z)$ | 음수는 0, 양수는 그대로 | 은닉층(현재 표준) |
현재 딥러닝에서 은닉층에는 ReLU가 거의 표준입니다. 계산이 빠르고 학습이 잘 되기 때문입니다. 출력층에서 0에서 1 사이 확률이 필요하면 시그모이드를 씁니다.
개념 4. 각 뉴런은 무엇을 배우는가
섹션 제목: “개념 4. 각 뉴런은 무엇을 배우는가”TensorFlow Playground의 가장 훌륭한 기능은 각 뉴런 옆에 작은 그림을 보여준다는 점입니다. 이 그림은 해당 뉴런이 입력 공간을 어떻게 가르는지 보여줍니다. XOR 데이터에 은닉 뉴런 2개를 썼을 때 보통 다음 현상이 나타납니다.
- 뉴런 1: “x₁ + x₂ > 0.5” 같은 왼쪽 아래 대각선을 긋습니다
- 뉴런 2: “x₁ + x₂ > 1.5” 같은 오른쪽 위 대각선을 긋습니다
- 출력층: 두 결과를 “첫째는 참, 둘째는 거짓일 때만 1” 식으로 조합합니다
이것은 AND와 OR로 XOR을 만드는 고전적인 방법과 정확히 같은 구조입니다. 다층 신경망이 학습하는 것은 문제를 부분 문제로 쪼개는 방법이라고 볼 수 있습니다.
🔧 실습 1. TensorFlow Playground로 XOR 정복
섹션 제목: “🔧 실습 1. TensorFlow Playground로 XOR 정복”접속 및 초기 설정
섹션 제목: “접속 및 초기 설정”브라우저에서 다음 주소로 접속합니다.
playground.tensorflow.org
초기 화면이 뜨면 다음 순서로 설정합니다.
- DATA: 좌측 상단 4개 데이터셋 중 “Exclusive or” (XOR 패턴) 선택
- FEATURES: $X_1$과 $X_2$만 체크, 나머지(제곱·곱·사인) 전부 해제
- HIDDEN LAYERS: 1개 층, 뉴런 2개로 설정
- Activation: 우측 상단에서 “Tanh” 선택
- Learning rate: 0.03 (기본값)
좌측 상단 재생(▶) 버튼을 눌러 학습을 시작합니다.
관찰 포인트
섹션 제목: “관찰 포인트”학습이 진행되면서 다음을 기록합니다.
| 관찰 항목 | 기록란 |
|---|---|
| 학습 시작 시 Test loss | |
| 1,000 epoch 후 Test loss | |
| 최종 결정 경계 모양(직선/곡선) | |
| 은닉 뉴런 1의 그림이 보여주는 경계선 | |
| 은닉 뉴런 2의 그림이 보여주는 경계선 |
일반적으로 Test loss가 0.01 아래로 내려가면 성공입니다. 우측의 큰 그래프에서 경계선이 S자 또는 곡선 형태로 휘어진 모습을 볼 수 있습니다.
비교 실험
섹션 제목: “비교 실험”같은 XOR 데이터에 대해 다음 세 가지 설정을 비교합니다.
| 실험 번호 | 은닉층 수 | 뉴런 수 | 예상 결과 |
|---|---|---|---|
| A | 0 (단층) | - | 실패. Loss가 0.25 근처에서 멈춤 |
| B | 1 | 2 | 성공. 곡선 경계 |
| C | 1 | 4 | 성공. 더 부드러운 경계 |
🔧 실습 2. 원형·나선형 데이터로 확장
섹션 제목: “🔧 실습 2. 원형·나선형 데이터로 확장”XOR을 풀었다면 더 어려운 데이터에 도전합니다.
원형 데이터 (Circle)
섹션 제목: “원형 데이터 (Circle)”중심에 파란 점, 바깥 링에 주황 점이 있는 데이터입니다.
- 시도 1: 은닉층 1개, 뉴런 2개 → 대부분 실패 (경계가 직선 조합으로만 가능)
- 시도 2: 은닉층 1개, 뉴런 4개 → 원형 경계 형성
- 시도 3: 은닉층 2개, 뉴런 4개+2개 → 매끄러운 원
나선형 데이터 (Spiral)
섹션 제목: “나선형 데이터 (Spiral)”두 나선이 서로 꼬여 있는 가장 어려운 데이터입니다.
| 구성 | 결과 |
|---|---|
| 은닉 1층, 뉴런 4개 | 거의 실패 |
| 은닉 2층, 뉴런 4+4 | 부분 성공, 중심부 오류 |
| 은닉 3층, 뉴런 6+4+4 | 성공, 나선을 따라 감김 |
관찰: 데이터가 복잡해질수록 층과 뉴런이 더 많이 필요합니다. 이것이 “딥”러닝이라고 부르는 이유입니다.
💻 실습 3. Keras로 XOR 직접 학습시키기
섹션 제목: “💻 실습 3. Keras로 XOR 직접 학습시키기”실행 환경
섹션 제목: “실행 환경”Google Colab (colab.research.google.com)에서 새 노트북을 엽니다. Python 3.10+, TensorFlow 2.x가 이미 설치되어 있습니다.
v1. 먼저 “실패하는” 단층 퍼셉트론
섹션 제목: “v1. 먼저 “실패하는” 단층 퍼셉트론”은닉층 없이 입력 → 출력으로 바로 연결하는 신경망입니다. XOR에서 실패하는지 직접 확인합니다.
import numpy as npimport tensorflow as tffrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense
# XOR 진리표 4개 샘플X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=np.float32)y = np.array([[0], [1], [1], [0]], dtype=np.float32)
# 은닉층 없이 바로 출력층 (단층 퍼셉트론과 동치)model_v1 = Sequential([ Dense(1, activation='sigmoid', input_shape=(2,)) # <- 여기가 단층 구조])
model_v1.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])history = model_v1.fit(X, y, epochs=500, verbose=0)
# 결과 확인print("최종 예측:")print(model_v1.predict(X, verbose=0).round(2))print(f"정확도: {history.history['accuracy'][-1]:.2f}")실행 결과 예시:
최종 예측:[[0.5 ] [0.5 ] [0.5 ] [0.5 ]]정확도: 0.50네 개 모두 0.5로 예측합니다. 정확도 50%는 그냥 찍는 것과 같은 수준입니다. 4차시에서 예고했던 실패가 코드로도 재현되었습니다.
위 코드의 9번째 줄 Dense(1, activation='sigmoid', input_shape=(2,))가 바로 단층 퍼셉트론입니다. 은닉층이 없어서 XOR을 학습할 수 없습니다.
v2. 은닉층 추가 — XOR 해결
섹션 제목: “v2. 은닉층 추가 — XOR 해결”은닉층 하나를 추가합니다. 이것이 오늘 수업의 핵심입니다.
import numpy as npimport tensorflow as tffrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=np.float32)y = np.array([[0], [1], [1], [0]], dtype=np.float32)
model_v2 = Sequential([ Dense(4, activation='tanh', input_shape=(2,)), # <- 여기가 은닉층 (뉴런 4개) Dense(1, activation='sigmoid') # <- 여기가 출력층])
model_v2.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])history = model_v2.fit(X, y, epochs=2000, verbose=0)
print("최종 예측:")print(model_v2.predict(X, verbose=0).round(2))print(f"정확도: {history.history['accuracy'][-1]:.2f}")실행 결과 예시:
최종 예측:[[0.03] [0.97] [0.97] [0.04]]정확도: 1.00정확도 100%. (0,0)과 (1,1)은 0에 가깝고, (0,1)과 (1,0)은 1에 가깝게 예측합니다.
v1에서 10번째 줄 Dense(4, activation='tanh', ...) 한 줄만 추가했을 뿐인데 문제가 풀렸습니다. 이 한 줄이 개념 2의 식 (2)에서 $\mathbf{h} = \sigma(\mathbf{W}_1 \mathbf{x} + \mathbf{b}_1)$에 해당하는 은닉층입니다.
에러 경험: 활성화 함수를 빼면 어떻게 될까?
섹션 제목: “에러 경험: 활성화 함수를 빼면 어떻게 될까?”은닉층만 있고 활성화 함수를 빼면 어떻게 되는지 직접 봅시다.
# 활성화 함수를 일부러 'linear'로 (= 활성화 없음)model_err = Sequential([ Dense(4, activation='linear', input_shape=(2,)), # <- 비선형성 제거 Dense(1, activation='sigmoid')])model_err.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])model_err.fit(X, y, epochs=2000, verbose=0)print(model_err.predict(X, verbose=0).round(2))실행 결과 예시:
[[0.5 ] [0.5 ] [0.5 ] [0.5 ]]은닉층이 있는데도 v1과 똑같이 실패합니다.
원인: activation='linear'는 $\sigma(z) = z$, 즉 아무 변환도 하지 않음과 같습니다. 그러면 $\mathbf{W}_2 \mathbf{W}_1 \mathbf{x}$가 되어 직선 하나와 수학적으로 동일해집니다. 개념 3에서 설명한 “활성화 함수가 비선형성의 원천”이라는 말이 코드로 증명된 순간입니다.---
v3. ReLU로 바꾸고 학습 시각화하기
섹션 제목: “v3. ReLU로 바꾸고 학습 시각화하기”현대 딥러닝의 표준인 ReLU로 활성화 함수를 바꾸고, 학습 곡선을 그려 봅니다.
import numpy as npimport tensorflow as tfimport matplotlib.pyplot as pltfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=np.float32)y = np.array([[0], [1], [1], [0]], dtype=np.float32)
model_v3 = Sequential([ Dense(4, activation='relu', input_shape=(2,)), # <- ReLU로 변경 Dense(1, activation='sigmoid')])
model_v3.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])history = model_v3.fit(X, y, epochs=2000, verbose=0)
# 학습 곡선 그리기plt.plot(history.history['loss'])plt.xlabel('Epoch')plt.ylabel('Loss')plt.title('XOR 학습 곡선 (ReLU)')plt.grid(True)plt.show()
print("최종 예측:", model_v3.predict(X, verbose=0).round(2).flatten())실행 결과 예시:
최종 예측: [0.02 0.98 0.98 0.02]학습 곡선은 초반에 0.69 근처에서 시작해 급격히 떨어진 뒤 0에 가까워집니다. 0.69는 ln(2)로, 무작위 추측의 손실값입니다. 여기서 내려가기 시작하면 학습이 진행되고 있다는 신호입니다.
결정 경계 시각화 (보너스)
섹션 제목: “결정 경계 시각화 (보너스)”학습된 신경망이 실제로 어떤 경계선을 그렸는지 그림으로 확인합니다.
import numpy as npimport matplotlib.pyplot as plt
# 0-1 사이 격자점 생성xx, yy = np.meshgrid(np.linspace(-0.2, 1.2, 100), np.linspace(-0.2, 1.2, 100))grid = np.c_[xx.ravel(), yy.ravel()].astype(np.float32)
# 모든 격자점의 예측값Z = model_v3.predict(grid, verbose=0).reshape(xx.shape)
plt.contourf(xx, yy, Z, levels=20, cmap='RdBu_r', alpha=0.7)plt.colorbar(label='예측값')# 실제 4개 XOR 점 표시plt.scatter([0, 1], [0, 1], c='blue', s=200, label='클래스 0', edgecolors='black')plt.scatter([0, 1], [1, 0], c='red', s=200, label='클래스 1', edgecolors='black')plt.xlabel('x1'); plt.ylabel('x2')plt.title('XOR 결정 경계')plt.legend()plt.show()예상 결과: 대각선 방향으로 파란-빨강 영역이 번갈아 나타나는 곡선 경계가 보입니다. 직선이 아니라 휘어진 경계가 네 점을 정확히 나눕니다.
🤔 토론 / 탐구 활동
섹션 제목: “🤔 토론 / 탐구 활동”활동 유형: 모둠(4인) · 25분
활동 1. 뉴런 수 최소값 찾기 (10분)
섹션 제목: “활동 1. 뉴런 수 최소값 찾기 (10분)”TensorFlow Playground에서 XOR 데이터에 대해 Test loss 0.05 이하를 달성할 수 있는 최소 뉴런 수를 찾습니다. 뉴런 1개, 2개, 3개 순으로 늘려가며 기록합니다.
| 은닉층 구성 | 성공 여부 | 학습 시간(epoch) |
|---|---|---|
| 뉴런 1개 | ||
| 뉴런 2개 | ||
| 뉴런 3개 |
활동 2. 토론 질문
섹션 제목: “활동 2. 토론 질문”활동 3. 모둠 발표
섹션 제목: “활동 3. 모둠 발표”모둠별로 “우리가 찾은 최소 구조”와 “그 이유”를 1분씩 발표합니다.
🧪 연습 문제
섹션 제목: “🧪 연습 문제”기초. XOR 대신 AND 문제 풀기
섹션 제목: “기초. XOR 대신 AND 문제 풀기”XOR 대신 AND 진리표 [[0],[0],[0],[1]]을 학습시키는 코드를 작성하세요. 은닉층이 없어도 풀리는지 확인합니다.
힌트
AND는 선형 분리 가능한 문제입니다. 네 점을 그려 보면 하나의 직선으로 (1,1)만 분리할 수 있습니다. 단층으로 충분합니다.
정답 코드
import numpy as npfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense
X = np.array([[0,0],[0,1],[1,0],[1,1]], dtype=np.float32)y = np.array([[0],[0],[0],[1]], dtype=np.float32)
model = Sequential([Dense(1, activation='sigmoid', input_shape=(2,))])model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])model.fit(X, y, epochs=1000, verbose=0)print(model.predict(X, verbose=0).round(2))# 예상: [[0.01], [0.06], [0.06], [0.93]]응용. 3입력 XOR
섹션 제목: “응용. 3입력 XOR”입력이 3개인 “홀수 개의 1이 있으면 1을 출력”하는 문제를 신경망으로 풀어 보세요. 데이터는 8개 샘플입니다.
힌트
입력 3개, 출력 1개입니다. 은닉 뉴런은 4-8개 정도면 충분합니다. input_shape=(3,)로 바꾸는 것을 잊지 마세요.
정답 코드
import numpy as npfrom itertools import productfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense
X = np.array(list(product([0,1], repeat=3)), dtype=np.float32)y = np.array([[sum(row) % 2] for row in X], dtype=np.float32)
model = Sequential([ Dense(8, activation='relu', input_shape=(3,)), Dense(1, activation='sigmoid')])model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])model.fit(X, y, epochs=3000, verbose=0)print(np.hstack([X, model.predict(X, verbose=0).round(2)]))도전. 원형 데이터 분류기
섹션 제목: “도전. 원형 데이터 분류기”sklearn.datasets.make_circles로 생성한 원형 데이터(200개)를 학습시키는 신경망을 설계하세요. 정확도 95% 이상을 목표로 합니다.
힌트
원형 경계를 만들려면 은닉층이 여러 방향의 직선을 조합해야 합니다. 뉴런 8개 정도부터 시작해 보세요. 데이터를 train/test로 나누는 것도 잊지 마세요.
정답 코드
import numpy as npfrom sklearn.datasets import make_circlesfrom sklearn.model_selection import train_test_splitfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense
X, y = make_circles(n_samples=200, noise=0.1, factor=0.5, random_state=42)X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model = Sequential([ Dense(8, activation='relu', input_shape=(2,)), Dense(8, activation='relu'), Dense(1, activation='sigmoid')])model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])model.fit(X_train, y_train, epochs=200, verbose=0)loss, acc = model.evaluate(X_test, y_test, verbose=0)print(f"테스트 정확도: {acc:.2f}")💼 실무에서는 이렇게 씁니다
섹션 제목: “💼 실무에서는 이렇게 씁니다”오늘 배운 Dense(뉴런수, activation=...) 두 줄 구조는 실무 AI의 기초 뼈대입니다.
- 신용카드 사기 탐지: 거래 특성 30여 개를 입력받아
Dense(64) → Dense(32) → Dense(1, sigmoid)구조로 사기 여부를 예측합니다. XOR 학습과 코드 형태가 거의 같습니다. - 이미지 분류의 마지막 층: CNN이 이미지에서 뽑아낸 특성 벡터를 받아 최종 분류를 하는 부분도
Dense층입니다. 입력이 픽셀이 아닌 “이미 추출된 특성”이라는 점만 다릅니다. - 추천 시스템: 사용자·상품 임베딩을 결합해 “이 사용자가 이 상품을 살 확률”을 출력하는 최종 층도 Dense + sigmoid입니다.
오늘 XOR 문제를 푼 코드가 사실은 현업 AI 엔지니어가 매일 쓰는 코드 패턴과 같습니다. 데이터만 커지고 층만 깊어질 뿐 구조는 동일합니다.
🔗 참고 자료
섹션 제목: “🔗 참고 자료”📎 TensorFlow Playground
섹션 제목: “📎 TensorFlow Playground”브라우저에서 신경망을 시각적으로 조작해볼 수 있는 공식 시뮬레이터. playground.tensorflow.org →
📎 Keras 공식 문서 - Dense 층
섹션 제목: “📎 Keras 공식 문서 - Dense 층”Dense 층의 모든 매개변수와 사용 예시. keras.io/api/layers/core_layers/dense/ →
📎 3Blue1Brown - 신경망 시리즈
섹션 제목: “📎 3Blue1Brown - 신경망 시리즈”신경망의 직관을 애니메이션으로 설명하는 유튜브 시리즈. 한국어 자막 지원 →
📝 형성 평가
섹션 제목: “📝 형성 평가”객관식 1. 단층 퍼셉트론으로 XOR 문제를 풀 수 없는 근본적인 이유는 무엇입니까?
① 학습률이 너무 작아서 ② 데이터가 4개뿐이어서 ③ 결정 경계가 하나의 직선이기 때문에 ④ 활성화 함수가 시그모이드여서
정답 확인
정답: ③ 단층 퍼셉트론의 결정 경계는 $w_1 x_1 + w_2 x_2 + b = 0$이라는 직선 하나입니다. XOR의 네 점은 대각선 방향으로 같은 클래스가 놓여 있어 어떤 직선으로도 분리할 수 없습니다. 이것을 “선형 분리 불가능”이라고 합니다.
객관식 2. Keras 코드에서 Dense(4, activation='linear') 은닉층을 추가해도 XOR이 풀리지 않는 이유는?
① 뉴런 4개가 너무 적어서
② linear 활성화는 비선형 변환을 하지 않아 여러 층이 한 층과 같아지기 때문
③ Dense 층 대신 Conv2D를 써야 하기 때문
④ 학습 epoch이 부족해서
정답 확인
정답: ②
linear는 $\sigma(z) = z$로 아무 변환도 하지 않습니다. 이 경우 $\mathbf{W}_2(\mathbf{W}_1 \mathbf{x}) = (\mathbf{W}_2 \mathbf{W}_1)\mathbf{x}$가 되어, 은닉층이 있어도 수학적으로는 하나의 직선을 그리는 단층과 같아집니다. 비선형 활성화(tanh, ReLU, sigmoid 등)가 있어야 공간이 “휘어져” 곡선 경계가 생깁니다.
객관식 3. TensorFlow Playground에서 나선형(Spiral) 데이터를 분류하려 할 때, 가장 효과적으로 작동할 가능성이 높은 설정은?
① 은닉층 0개 ② 은닉층 1개, 뉴런 2개 ③ 은닉층 3개, 뉴런 6-6-4 ④ 은닉층 1개, 뉴런 1000개
정답 확인
정답: ③ 복잡한 패턴일수록 “깊이”(층의 수)가 중요합니다. 얕고 넓은 신경망(④)보다 적절히 깊은 신경망(③)이 계층적 특성을 잘 학습합니다. 이것이 “딥러닝”이라는 이름의 유래입니다.
서술형 1. “은닉층이 없으면 XOR을 풀 수 없다”는 사실을 학교 후배에게 설명한다면 어떻게 하겠습니까? (1) 기하학적 이유, (2) 은닉층이 하는 역할, (3) 활성화 함수의 필요성을 모두 포함해 3-5문장으로 서술하세요.
예시 답안
XOR은 네 점에서 같은 클래스가 대각선으로 놓여 있어서, 평면에 그리는 직선 한 개로는 나눌 수 없습니다(기하학적 이유). 은닉층은 입력을 여러 직선으로 동시에 바라본 결과를 만들어, 출력층이 그것들을 조합해 곡선 경계를 만들 수 있게 해 줍니다(은닉층 역할). 단, 활성화 함수가 없으면 여러 층을 쌓아도 결국 직선 하나와 같아지기 때문에, 층 사이에 tanh이나 ReLU 같은 비선형 함수가 꼭 있어야 “휘어짐”이 생깁니다(활성화 필요성).
자기점검 체크리스트
- 은닉층이 비선형 문제를 해결하는 원리를 직선과 곡선의 비유로 설명할 수 있다
- TensorFlow Playground에서 XOR·원형·나선형 데이터를 분류하는 구조를 찾을 수 있다
- Keras Sequential API로 Dense 2층 신경망을 작성해 XOR을 학습시킬 수 있다
- “한 개의 자로는 그릴 수 없는 경계를, 두 개의 자를 합치면 그릴 수 있을까?”에 자신의 답을 말할 수 있다
💭 성찰
섹션 제목: “💭 성찰”수업을 마치며 노트에 다음 세 가지를 적어 보세요.
- 오늘 수업에서 가장 인상 깊었던 순간은 언제입니까? (예: 단층이 실패한 순간, v2에서 한 줄 추가로 풀린 순간, 결정 경계가 휘는 그림 등)
- Playground의 은닉 뉴런 그림을 보며 새롭게 이해한 것이 있다면 무엇입니까?
- 은닉층의 개수나 뉴런 수를 바꿔 보고 싶은 실험이 있다면 어떤 것입니까? 왜 그 실험이 궁금한가요?
🔗 다음 차시 미리보기
섹션 제목: “🔗 다음 차시 미리보기”오늘 Keras의 model.fit()은 단 한 줄이었지만, 그 안에서 신경망은 수천 번의 시행착오를 거쳐 가중치를 조금씩 수정했습니다. 6차시에서는 그 내부를 열어 경사하강법과 역전파가 어떻게 오차를 거꾸로 전달하며 가중치를 업데이트하는지 들여다봅니다.
다음 질문: “신경망은 자신이 얼마나 틀렸는지 어떻게 알고, 그 책임을 각 뉴런에게 어떻게 나눠줄까요?”