4차시: 퍼셉트론 - 뉴런을 흉내 낸 최초의 학습 기계
🎯 이 차시의 핵심 주제
섹션 제목: “🎯 이 차시의 핵심 주제”🧠 퍼셉트론의 수학
섹션 제목: “🧠 퍼셉트론의 수학”가중합과 활성화 함수 두 줄로 뉴런을 표현합니다.
🔧 NumPy 구현
섹션 제목: “🔧 NumPy 구현”파이썬 코드 10줄로 AND·OR 게이트를 만듭니다.
💬 결정 경계 탐구
섹션 제목: “💬 결정 경계 탐구”가중치 슬라이더를 돌리며 직선이 회전하는 것을 관찰합니다.
📝 XOR의 벽
섹션 제목: “📝 XOR의 벽”한 개의 직선으로 풀 수 없는 문제가 있음을 직접 확인합니다.
⏱️ 수업 흐름
섹션 제목: “⏱️ 수업 흐름”도입: 뉴런에서 수식까지 (15분)
섹션 제목: “도입: 뉴런에서 수식까지 (15분)”생물학적 뉴런의 작동 원리를 관찰한 뒤, 입력·가중치·임계값이라는 세 가지 요소로 단순화합니다. 퍼셉트론 수식을 유도합니다.
구현: NumPy로 AND 게이트 만들기 (20분)
섹션 제목: “구현: NumPy로 AND 게이트 만들기 (20분)”v1에서 v3까지 점진적으로 코드를 발전시키며 퍼셉트론을 구현합니다. OR 게이트도 가중치만 바꿔 완성합니다.
탐구: 결정 경계 시각화 (20분)
섹션 제목: “탐구: 결정 경계 시각화 (20분)”가중치 w1, w2, bias를 바꾸며 2D 평면 위의 결정 경계선이 어떻게 움직이는지 관찰합니다.
클라이맥스: XOR에 도전하고 실패하기 (20분)
섹션 제목: “클라이맥스: XOR에 도전하고 실패하기 (20분)”XOR 게이트를 만드는 퍼셉트론을 찾으려 시도하고, 어떤 가중치로도 풀 수 없음을 확인합니다.
정리 및 평가 (5분)
섹션 제목: “정리 및 평가 (5분)”형성 평가와 성찰을 통해 ‘다층’의 필요성을 정리합니다.
📚 핵심 개념
섹션 제목: “📚 핵심 개념”개념 1. 뉴런을 수식으로 옮기기
섹션 제목: “개념 1. 뉴런을 수식으로 옮기기”커피숍 갈지 말지 결정하는 상황을 떠올려봅니다. 판단에는 여러 입력이 들어옵니다. 친구가 가자고 하는지($x_1$), 과제가 끝났는지($x_2$), 지갑 사정은 괜찮은지($x_3$). 각 요소의 중요도(가중치) 는 사람마다 다릅니다. 친구가 중요하면 $w_1$이 크고, 돈이 중요하면 $w_3$가 큽니다. 모든 요소의 중요도 가중 합계가 내 결심의 문턱을 넘으면 “간다”, 못 넘으면 “안 간다”로 결정됩니다.
생물학적 뉴런도 동일한 구조로 동작합니다. 수상돌기로 여러 신호가 들어오고, 세포체에서 합산되어, 임계값을 넘으면 축삭을 따라 발화합니다. 1958년 로젠블랫(Rosenblatt)은 이 구조를 수식 두 줄로 정리했습니다. 이것이 퍼셉트론(Perceptron) 입니다.
퍼셉트론의 수학적 정의
$$ z = w_1 x_1 + w_2 x_2 + b $$
$$ y = \begin{cases} 1 & \text{if } z \geq 0 \ 0 & \text{if } z < 0 \end{cases} $$
기호의 의미는 다음과 같습니다.
| 기호 | 의미 | 역할 |
|---|---|---|
| $x_1, x_2$ | 입력값 | 판단 재료 (예: 센서 값, 픽셀 밝기) |
| $w_1, w_2$ | 가중치(weight) | 각 입력을 얼마나 중요하게 볼지 |
| $b$ | 편향(bias) | 결정의 문턱을 조절 |
| $z$ | 가중합 | 입력과 가중치의 선형 결합 |
| $y$ | 출력 | 0 또는 1 (발화 여부) |
$z \geq 0$이면 1, 아니면 0을 내는 함수를 계단 함수(step function) 라고 부릅니다. 가중합 위에 덮인 이 함수가 활성화 함수(activation function) 입니다.
flowchart LR X1[입력 x1] -->|가중치 w1| SUM[가중합<br/>z = w1·x1 + w2·x2 + b] X2[입력 x2] -->|가중치 w2| SUM B[편향 b] --> SUM SUM --> ACT[계단 함수] ACT --> Y[출력 y<br/>0 또는 1]
여러분이 매일 쓰는 스마트폰의 얼굴 잠금 해제 첫 단계, 이메일 스팸 필터 초기 버전이 모두 이 구조에서 출발했습니다.
개념 2. NumPy로 퍼셉트론 구현하기
섹션 제목: “개념 2. NumPy로 퍼셉트론 구현하기”개념을 코드로 옮기겠습니다. 목표는 AND 게이트입니다. 두 입력이 모두 1일 때만 1을 출력하는 논리 연산입니다.
| $x_1$ | $x_2$ | AND 결과 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
v1: 가중합만 계산하기 (가장 단순한 버전)
섹션 제목: “v1: 가중합만 계산하기 (가장 단순한 버전)”# 실행 환경: Python 3.10+, numpy 필요import numpy as np
x = np.array([1, 1]) # 입력: x1=1, x2=1w = np.array([0.5, 0.5]) # 가중치: 일단 같은 값b = -0.7 # 편향: 임계값 역할
z = np.dot(x, w) + b # 가중합print(z)0.3np.dot(x, w)는 $w_1 x_1 + w_2 x_2$를 한 줄로 계산합니다. 두 배열의 내적입니다.
v2: 활성화 함수 추가하기
섹션 제목: “v2: 활성화 함수 추가하기”v1은 숫자만 뱉습니다. 0 또는 1로 바꾸려면 계단 함수가 필요합니다.
import numpy as np
def step(z): # z가 0 이상이면 1, 아니면 0 <- 여기가 활성화 함수 return 1 if z >= 0 else 0
def perceptron(x, w, b): z = np.dot(x, w) + b # <- 여기가 가중합 return step(z) # <- 여기가 활성화
x = np.array([1, 1])w = np.array([0.5, 0.5])b = -0.7
print(perceptron(x, w, b))1위 코드의 9번째 줄 z = np.dot(x, w) + b가 바로 가중합 수식 $z = w_1 x_1 + w_2 x_2 + b$입니다. 10번째 줄 step(z)가 활성화 함수입니다.
v3: AND 게이트 완성 - 모든 입력 조합 테스트
섹션 제목: “v3: AND 게이트 완성 - 모든 입력 조합 테스트”함수가 네 가지 입력 모두에서 올바르게 동작하는지 확인합니다.
import numpy as np
def step(z): return 1 if z >= 0 else 0
def perceptron(x, w, b): z = np.dot(x, w) + b return step(z)
# AND 게이트용 가중치와 편향w_and = np.array([0.5, 0.5])b_and = -0.7
# 네 가지 입력 조합을 모두 테스트inputs = [(0, 0), (0, 1), (1, 0), (1, 1)]print("AND 게이트 진리표")print("x1 x2 | 출력")print("-" * 18)for x1, x2 in inputs: x = np.array([x1, x2]) y = perceptron(x, w_and, b_and) print(f" {x1} {x2} | {y}")AND 게이트 진리표x1 x2 | 출력------------------ 0 0 | 0 0 1 | 0 1 0 | 0 1 1 | 1AND가 동작합니다. 가중치 두 개와 편향 한 개만으로 논리 게이트를 학습시킨 것입니다.
OR 게이트 - 편향만 바꾸면 됩니다
섹션 제목: “OR 게이트 - 편향만 바꾸면 됩니다”OR은 “둘 중 하나라도 1이면 1”입니다. AND보다 문턱이 낮아야 합니다.
import numpy as np
def step(z): return 1 if z >= 0 else 0
def perceptron(x, w, b): return step(np.dot(x, w) + b)
# OR 게이트: 가중치는 같고, 편향만 올림 (문턱을 낮춤)w_or = np.array([0.5, 0.5])b_or = -0.2 # <- AND는 -0.7, OR은 -0.2
for x1, x2 in [(0, 0), (0, 1), (1, 0), (1, 1)]: x = np.array([x1, x2]) print(f"OR({x1},{x2}) = {perceptron(x, w_or, b_or)}")OR(0,0) = 0OR(0,1) = 1OR(1,0) = 1OR(1,1) = 1편향 $b$만 $-0.7$에서 $-0.2$로 바꿨더니 AND가 OR로 바뀌었습니다. 편향은 결정의 문턱 높이입니다.
🚨 에러 경험: 가중치를 잘못 주면?
섹션 제목: “🚨 에러 경험: 가중치를 잘못 주면?”아래 코드를 실행하면 어떤 결과가 나올지 예측해봅니다.
import numpy as np
def step(z): return 1 if z >= 0 else 0
def perceptron(x, w, b): return step(np.dot(x, w) + b)
# "AND 게이트를 만들겠다"며 모두 양수로 설정w = np.array([0.5, 0.5])b = 0.1 # 편향을 양수로!
for x1, x2 in [(0, 0), (0, 1), (1, 0), (1, 1)]: x = np.array([x1, x2]) print(f"({x1},{x2}) -> {perceptron(x, w, b)}")(0,0) -> 1(0,1) -> 1(1,0) -> 1(1,1) -> 1에러 메시지는 없지만 결과가 전부 1입니다. 원인: 편향이 양수이면 입력이 모두 0일 때도 $z = 0 + 0 + 0.1 = 0.1 \geq 0$이라 1을 출력합니다. 결정의 문턱이 너무 낮아진 것입니다. 논리 에러는 파이썬이 잡아주지 않습니다. 직접 진리표와 대조해야 발견됩니다.
개념 3. 결정 경계 — 직선이 두 영역을 가른다
섹션 제목: “개념 3. 결정 경계 — 직선이 두 영역을 가른다”퍼셉트론이 0과 1을 바꾸는 경계는 $z = 0$인 지점입니다.
$$ w_1 x_1 + w_2 x_2 + b = 0 $$
이 식을 $x_2$에 대해 풀면 $x_2 = -\dfrac{w_1}{w_2} x_1 - \dfrac{b}{w_2}$입니다. 직선의 방정식입니다. 즉 퍼셉트론은 2D 평면을 하나의 직선으로 두 영역 으로 나누는 장치입니다. 직선의 한쪽은 “1”, 반대쪽은 “0”입니다.
AND의 경우 $w_1 = w_2 = 0.5$, $b = -0.7$이므로 경계선은 $0.5 x_1 + 0.5 x_2 - 0.7 = 0$, 즉 $x_1 + x_2 = 1.4$가 됩니다. 점 $(1,1)$만 직선 위쪽에 있고 나머지 세 점은 아래쪽에 있습니다. 그래서 $(1,1)$만 1을 출력합니다.
결정 경계 시각화 실습
import numpy as npimport matplotlib.pyplot as plt
def plot_decision_boundary(w1, w2, b, title): # 네 가지 입력 점 points = [(0,0), (0,1), (1,0), (1,1)] labels_and = [0, 0, 0, 1] # AND의 정답
fig, ax = plt.subplots(figsize=(5, 5)) for (x1, x2), y in zip(points, labels_and): color = 'red' if y == 1 else 'blue' ax.scatter(x1, x2, c=color, s=200, edgecolor='black', zorder=3)
# 결정 경계: w1*x1 + w2*x2 + b = 0 -> x2 = -(w1*x1 + b)/w2 x_line = np.linspace(-0.5, 1.5, 100) if w2 != 0: y_line = -(w1 * x_line + b) / w2 ax.plot(x_line, y_line, 'g--', linewidth=2, label='결정 경계')
ax.set_xlim(-0.5, 1.5) ax.set_ylim(-0.5, 1.5) ax.axhline(0, color='gray', lw=0.5) ax.axvline(0, color='gray', lw=0.5) ax.set_xlabel('x1'); ax.set_ylabel('x2') ax.set_title(title) ax.grid(True, alpha=0.3) ax.legend() plt.show()
# AND 게이트의 결정 경계plot_decision_boundary(0.5, 0.5, -0.7, "AND 게이트")실행하면 파란 점 3개(0 클래스)와 빨간 점 1개(1 클래스)를 초록 점선이 깔끔하게 가릅니다.
슬라이더처럼 값을 바꿔가며 관찰하기
# 편향만 바꿔가며 직선이 어떻게 이동하는지 확인for b in [-1.2, -0.7, -0.2, 0.3]: plot_decision_boundary(0.5, 0.5, b, f"b = {b}")$b$가 작아지면 직선이 오른쪽 위로, 커지면 왼쪽 아래로 평행 이동합니다. $w_1$과 $w_2$의 비율을 바꾸면 직선이 회전합니다.
| 파라미터 | 기하학적 효과 |
|---|---|
| $b$ (편향) | 직선의 평행 이동 |
| $w_1 : w_2$ 비율 | 직선의 기울기(회전) |
| $w_1, w_2$ 부호 반전 | ”1” 영역과 “0” 영역이 뒤집힘 |
개념 4. XOR의 벽 — 직선 하나로는 풀 수 없다
섹션 제목: “개념 4. XOR의 벽 — 직선 하나로는 풀 수 없다”XOR(배타적 논리합)은 “둘이 다를 때만 1”입니다.
| $x_1$ | $x_2$ | XOR |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
2D 평면에 점을 찍어봅니다. $(0,0)$과 $(1,1)$은 “0 클래스”(파란색), $(0,1)$과 $(1,0)$은 “1 클래스”(빨간색)입니다. 두 클래스는 대각선 방향으로 교차 배치됩니다.
flowchart LR A["(0,0) → 0<br/>파랑"] B["(0,1) → 1<br/>빨강"] C["(1,0) → 1<br/>빨강"] D["(1,1) → 0<br/>파랑"]
직접 실패해보기: XOR을 만들 수 있는 $w_1, w_2, b$를 찾아봅니다.
import numpy as np
def step(z): return 1 if z >= 0 else 0
def perceptron(x, w, b): return step(np.dot(x, w) + b)
# XOR 정답xor_truth = {(0,0): 0, (0,1): 1, (1,0): 1, (1,1): 0}
# 아무 가중치나 시도해봅니다candidates = [ (np.array([0.5, 0.5]), -0.2), # OR과 유사 (np.array([1.0, -1.0]), 0.0), # 대각선 시도 (np.array([-0.5, 0.5]), 0.1), (np.array([0.7, 0.3]), -0.5),]
for w, b in candidates: correct = 0 for (x1, x2), truth in xor_truth.items(): pred = perceptron(np.array([x1, x2]), w, b) if pred == truth: correct += 1 print(f"w={w}, b={b}: {correct}/4 정답")w=[0.5 0.5], b=-0.2: 2/4 정답w=[ 1. -1.], b=0.0: 3/4 정답w=[-0.5 0.5], b=0.1: 2/4 정답w=[0.7 0.3], b=-0.5: 2/4 정답4/4이 나오는 조합이 하나도 없습니다. 어떤 가중치를 넣어도 최대 3개까지만 맞습니다.
왜일까요? 빨간 점 두 개 $(0,1), (1,0)$은 대각선 양 끝에 있고, 파란 점 두 개 $(0,0), (1,1)$은 반대 대각선 양 끝에 있습니다. 하나의 직선으로는 이 네 점을 색깔별로 분리할 수 없습니다. 기하학적 사실입니다.이 한계를 선형 분리 가능성(linear separability) 의 한계라고 부릅니다. 1969년 민스키와 페퍼트가 저서 『퍼셉트론』에서 수학적으로 증명한 사실입니다. 이 발표 이후 신경망 연구는 약 15년간 겨울을 맞았습니다.
| 문제 | 선형 분리 가능? | 단층 퍼셉트론 |
|---|---|---|
| AND | ✅ 가능 | 풀림 |
| OR | ✅ 가능 | 풀림 |
| NAND | ✅ 가능 | 풀림 |
| XOR | ❌ 불가능 | 못 풂 |
해결책은 의외로 단순합니다. 직선을 두 개 이상 쓰면 됩니다. 퍼셉트론을 여러 층으로 쌓으면 첫 번째 층이 중간 특징(예: “OR이지만 AND는 아님”)을 만들고, 두 번째 층이 그 특징들을 다시 조합합니다. 이것이 다층 퍼셉트론(MLP) 이고, 현대 딥러닝의 출발점입니다.
flowchart LR X1[x1] --> H1[은닉 뉴런1<br/>OR 역할] X2[x2] --> H1 X1 --> H2[은닉 뉴런2<br/>NAND 역할] X2 --> H2 H1 --> OUT[출력 뉴런<br/>AND 역할] H2 --> OUT OUT --> Y[XOR 결과]
여러분이 사용하는 얼굴 인식, 음성 비서, 번역기는 모두 이 ‘쌓기’ 덕분에 가능합니다. 오늘 배운 퍼셉트론 하나가 벽돌 한 장이고, 다음 차시부터 이 벽돌을 어떻게 쌓을지 배웁니다.
🤔 토론 / 탐구 활동
섹션 제목: “🤔 토론 / 탐구 활동”활동 유형: 짝 활동 (2인)
활동 지시문
- 짝과 함께 아래 코드를 실행합니다.
w1,w2,b값을 자유롭게 바꿔가며 NAND 게이트(AND의 반대: 둘 다 1일 때만 0)를 만들어 봅니다. - 성공한 가중치 조합을 아래 표에 기록합니다.
- 그다음 같은 방식으로 XOR을 만들어 봅니다. 10분간 시도하고, 안 되면 “왜 안 되는가”를 짝에게 설명합니다.
import numpy as np
def perceptron(x1, x2, w1, w2, b): z = w1*x1 + w2*x2 + b return 1 if z >= 0 else 0
# 여기 값을 바꿔가며 시도합니다w1, w2, b = ?, ?, ?
for x1, x2 in [(0,0),(0,1),(1,0),(1,1)]: print(f"({x1},{x2}) -> {perceptron(x1, x2, w1, w2, b)}")기록표
| 게이트 | w1 | w2 | b | 성공 여부 |
|---|---|---|---|---|
| NAND | ||||
| XOR |
토론 질문
- AND를 만들던 가중치에서 어떤 부호를 바꾸면 NAND가 될까요?
- XOR을 만드는 데 실패했다면, 그 실패는 여러분의 탓입니까 아니면 퍼셉트론 자체의 한계입니까? 종이에 네 점을 찍고 직선을 그어보며 설명합니다.
- 만약 직선이 아니라 곡선 하나를 그릴 수 있다면 XOR을 풀 수 있을까요? 어떤 모양이어야 할까요?
🔧 실습 활동: 결정 경계 슬라이더
섹션 제목: “🔧 실습 활동: 결정 경계 슬라이더”ipywidgets를 사용하면 주피터 노트북에서 슬라이더로 가중치를 실시간 조작할 수 있습니다. 구글 코랩(Colab)에서 바로 실행됩니다.
1단계: 코랩 접속 및 코드 붙여넣기 (3분)
섹션 제목: “1단계: 코랩 접속 및 코드 붙여넣기 (3분)”colab.research.google.com 에서 새 노트북을 만들고 아래 코드를 붙여넣습니다.
2단계: 슬라이더 실행 (5분)
섹션 제목: “2단계: 슬라이더 실행 (5분)”셀을 실행하면 슬라이더 세 개가 나타납니다. w1, w2, b를 움직이며 직선이 어떻게 변하는지 관찰합니다.
3단계: AND/OR/XOR 도전 (7분)
섹션 제목: “3단계: AND/OR/XOR 도전 (7분)”토글 버튼으로 목표 게이트를 바꾸며, 네 점을 모두 올바르게 분류하는 조합을 찾아봅니다. XOR에서는 끝내 실패합니다.
# 실행 환경: Google Colab 또는 Jupyter Notebookimport numpy as npimport matplotlib.pyplot as pltfrom ipywidgets import interact, FloatSlider, Dropdown
# 세 가지 논리 게이트의 정답truth_tables = { 'AND': {(0,0):0, (0,1):0, (1,0):0, (1,1):1}, 'OR': {(0,0):0, (0,1):1, (1,0):1, (1,1):1}, 'XOR': {(0,0):0, (0,1):1, (1,0):1, (1,1):0},}
def simulate(w1, w2, b, gate): truth = truth_tables[gate] fig, ax = plt.subplots(figsize=(6, 6))
correct = 0 for (x1, x2), y in truth.items(): # 퍼셉트론 예측 pred = 1 if (w1*x1 + w2*x2 + b) >= 0 else 0 ok = (pred == y) if ok: correct += 1
# 정답 색상 (빨강=1, 파랑=0) + 예측 맞으면 테두리 초록, 틀리면 빨강 color = 'red' if y == 1 else 'blue' edge = 'lime' if ok else 'black' ax.scatter(x1, x2, c=color, s=400, edgecolor=edge, linewidth=3, zorder=3)
# 결정 경계 그리기 x_line = np.linspace(-0.5, 1.5, 100) if w2 != 0: y_line = -(w1 * x_line + b) / w2 ax.plot(x_line, y_line, 'g--', linewidth=2)
# 1영역 음영 처리 xx, yy = np.meshgrid(np.linspace(-0.5, 1.5, 200), np.linspace(-0.5, 1.5, 200)) zz = w1*xx + w2*yy + b ax.contourf(xx, yy, zz, levels=[0, 1e9], colors=['#ffcccc'], alpha=0.3)
ax.set_xlim(-0.5, 1.5); ax.set_ylim(-0.5, 1.5) ax.set_xlabel('x1'); ax.set_ylabel('x2') ax.set_title(f"{gate} | 정답 {correct}/4 | w1={w1:.2f}, w2={w2:.2f}, b={b:.2f}") ax.grid(True, alpha=0.3) plt.show()
interact(simulate, w1=FloatSlider(min=-2, max=2, step=0.1, value=0.5), w2=FloatSlider(min=-2, max=2, step=0.1, value=0.5), b =FloatSlider(min=-2, max=2, step=0.1, value=-0.7), gate=Dropdown(options=['AND','OR','XOR'], value='AND'));관찰 포인트
- AND 모드에서 $b$를 $-0.7$ 근처로 두면 “4/4 정답”이 뜹니다
- OR 모드에서 $b$를 $-0.2$ 근처로 조절하면 역시 “4/4 정답”이 됩니다
- XOR 모드에서 슬라이더를 어떻게 움직여도 “4/4 정답”은 나타나지 않습니다
🧩 연습 문제
섹션 제목: “🧩 연습 문제”기초: NAND 게이트 구현
섹션 제목: “기초: NAND 게이트 구현”AND의 결과를 뒤집은 것이 NAND입니다. 퍼셉트론 가중치 w_nand와 편향 b_nand를 설정하여 NAND 진리표를 만들어 봅니다.
힌트
AND는 $w=[0.5, 0.5], b=-0.7$이었습니다. “뒤집는다”는 것은 가중합의 부호를 반대로 만드는 것입니다. 모든 부호를 반대로 해봅니다.
정답 코드
import numpy as np
def step(z): return 1 if z >= 0 else 0
def perceptron(x, w, b): return step(np.dot(x, w) + b)
w_nand = np.array([-0.5, -0.5]) # AND 가중치의 부호 반대b_nand = 0.7 # AND 편향의 부호 반대
for x1, x2 in [(0,0),(0,1),(1,0),(1,1)]: print(f"NAND({x1},{x2}) = {perceptron(np.array([x1,x2]), w_nand, b_nand)}")NAND(0,0) = 1NAND(0,1) = 1NAND(1,0) = 1NAND(1,1) = 0응용: 3입력 AND 게이트
섹션 제목: “응용: 3입력 AND 게이트”입력이 세 개인 AND는 “셋 다 1일 때만 1”입니다. $x_1, x_2, x_3$를 받는 퍼셉트론을 구현합니다.
힌트
가중치 배열 길이를 3으로 늘리고, 편향은 “셋 다 1일 때만 문턱을 넘도록” 설정합니다. 가중치 합이 문턱보다 조금 크도록.
정답 코드
import numpy as np
def perceptron(x, w, b): return 1 if np.dot(x, w) + b >= 0 else 0
w = np.array([0.5, 0.5, 0.5])b = -1.2 # 세 입력이 모두 1일 때 합 1.5, -1.2 더하면 0.3 >= 0
for x1 in [0,1]: for x2 in [0,1]: for x3 in [0,1]: x = np.array([x1,x2,x3]) print(f"({x1},{x2},{x3}) -> {perceptron(x, w, b)}")(0,0,0) -> 0(0,0,1) -> 0(0,1,0) -> 0(0,1,1) -> 0(1,0,0) -> 0(1,0,1) -> 0(1,1,0) -> 0(1,1,1) -> 1도전: 두 퍼셉트론을 조합하여 XOR 만들기
섹션 제목: “도전: 두 퍼셉트론을 조합하여 XOR 만들기”XOR은 한 개의 퍼셉트론으로는 불가능하지만, NAND와 OR의 결과를 다시 AND로 묶으면 만들 수 있습니다. 즉 퍼셉트론을 두 층으로 쌓습니다.
힌트
XOR(x1, x2) = AND( OR(x1, x2), NAND(x1, x2) )
첫 번째 층에서 OR과 NAND를 각각 계산하고, 그 두 결과를 두 번째 층 AND의 입력으로 넣습니다.
정답 코드
import numpy as np
def perceptron(x, w, b): return 1 if np.dot(x, w) + b >= 0 else 0
def AND(x1, x2): return perceptron(np.array([x1,x2]), np.array([0.5, 0.5]), -0.7)
def OR(x1, x2): return perceptron(np.array([x1,x2]), np.array([0.5, 0.5]), -0.2)
def NAND(x1, x2): return perceptron(np.array([x1,x2]), np.array([-0.5,-0.5]), 0.7)
def XOR(x1, x2): s1 = OR(x1, x2) # 첫째 층 출력 1 s2 = NAND(x1, x2) # 첫째 층 출력 2 return AND(s1, s2) # 둘째 층
for x1, x2 in [(0,0),(0,1),(1,0),(1,1)]: print(f"XOR({x1},{x2}) = {XOR(x1,x2)}")XOR(0,0) = 0XOR(0,1) = 1XOR(1,0) = 1XOR(1,1) = 0두 층을 쌓자 직선 하나로 풀 수 없던 문제가 풀립니다. 이것이 다층 퍼셉트론의 힘입니다.
💼 실무에서는 이렇게 씁니다
섹션 제목: “💼 실무에서는 이렇게 씁니다”오늘 직접 만든 퍼셉트론은 현대 딥러닝 코드 안에 그대로 살아 있습니다.
- PyTorch의
nn.Linear: $z = Wx + b$를 계산합니다. 퍼셉트론의 가중합과 동일합니다. 가중치 행렬이 다차원으로 커졌을 뿐입니다. - 활성화 함수: 오늘 쓴 계단 함수 대신 실무에서는 ReLU($\max(0, z)$)나 시그모이드를 씁니다. 이유는 다음 차시에서 다룹니다(학습을 위해 미분 가능해야 함).
- 이진 분류 모델의 마지막 층: 스팸/정상, 양성/악성 같은 이진 판정은 본질적으로 “가중합이 문턱을 넘는가”입니다. 구조가 그대로입니다.
- 선형 SVM: 퍼셉트론의 직계 후손입니다. 결정 경계를 “마진이 최대가 되는 직선”으로 잡는다는 점만 다릅니다.
Keras로 쓰면 오늘 만든 퍼셉트론이 이렇게 한 줄이 됩니다.
# 실행 환경: Python 3.10+, tensorflow 2.xfrom tensorflow.keras import layers, models
model = models.Sequential([ layers.Dense(1, activation='sigmoid', input_shape=(2,)) # <- 퍼셉트론 한 개])model.compile(optimizer='sgd', loss='binary_crossentropy')Dense(1)이 바로 오늘 우리가 손으로 만든 퍼셉트론 하나입니다.
🔗 참고 자료
섹션 제목: “🔗 참고 자료”📎 TensorFlow Playground
섹션 제목: “📎 TensorFlow Playground”브라우저에서 신경망을 시각적으로 학습시키는 도구. XOR 데이터셋을 선택하고 ‘은닉층 개수’를 0 vs 1로 바꿔보면 오늘 체험이 그대로 확인됩니다. playground.tensorflow.org →
📎 3Blue1Brown - Neural Networks
섹션 제목: “📎 3Blue1Brown - Neural Networks”신경망을 기하학적으로 설명하는 유튜브 시리즈. 퍼셉트론의 결정 경계가 왜 직선인지 직관적으로 이해됩니다. →
📝 형성 평가
섹션 제목: “📝 형성 평가”객관식 1. 퍼셉트론의 수식 $y = \text{step}(w_1 x_1 + w_2 x_2 + b)$에서 편향 $b$의 역할은 무엇입니까?
① 입력의 크기를 조절한다 ② 결정의 문턱(임계값)을 조절한다 ③ 출력을 0과 1 사이로 정규화한다 ④ 입력이 음수일 때만 동작한다
정답 확인
정답: ② 편향 $b$는 가중합에 더해져서 계단 함수의 문턱을 실질적으로 이동시킵니다. $b$가 작을수록 문턱이 높아져 출력이 1이 되기 어렵고, $b$가 클수록 쉬워집니다. 2D 평면에서는 결정 경계 직선의 평행 이동으로 나타납니다.
객관식 2. 다음 중 단층 퍼셉트론으로 풀 수 없는 문제는?
① AND ② OR ③ NAND ④ XOR
정답 확인
정답: ④ XOR의 1-클래스 점 $(0,1), (1,0)$과 0-클래스 점 $(0,0), (1,1)$은 대각선 방향으로 교차 배치되어 있어 하나의 직선으로 분리할 수 없습니다. 이것을 선형 분리 불가능(not linearly separable)이라 하며, 다층 퍼셉트론이 필요한 이유입니다.
객관식 3. 2차원 입력 퍼셉트론의 결정 경계 방정식 $w_1 x_1 + w_2 x_2 + b = 0$에서, $w_1 : w_2$ 비율을 바꾸면 기하학적으로 어떤 변화가 일어납니까?
① 직선의 평행 이동 ② 직선의 회전(기울기 변화) ③ 직선이 곡선이 됨 ④ 아무 변화 없음
정답 확인
정답: ② $x_2 = -(w_1/w_2) x_1 - b/w_2$ 형태로 정리하면 기울기가 $-w_1/w_2$입니다. 이 비율이 바뀌면 직선이 회전합니다. 평행 이동은 $b$의 역할입니다.
서술형 1. XOR 게이트를 단층 퍼셉트론으로 구현할 수 없는 이유를 (1) 기하학적 관점과 (2) 해결 방향 두 가지로 설명하시오.
예시 답안
(1) 기하학적 관점: XOR의 1-클래스 점 $(0,1), (1,0)$과 0-클래스 점 $(0,0), (1,1)$은 단위 정사각형의 대각선 양 끝에 교차 배치되어 있습니다. 단층 퍼셉트론의 결정 경계는 직선 하나뿐이므로, 어떤 직선을 그어도 두 클래스를 완벽히 분리할 수 없습니다. 이를 선형 분리 불가능 문제라고 합니다.(2) 해결 방향: 퍼셉트론을 두 층 이상으로 쌓으면 됩니다. 첫 번째 층에서 OR과 NAND 같은 중간 특징을 각각 계산하고, 두 번째 층에서 그 두 출력을 AND로 묶으면 XOR을 만들 수 있습니다. 즉 직선 두 개를 조합하여 비선형 결정 경계를 만드는 것입니다. 이 구조가 다층 퍼셉트론(MLP) 이며, 현대 딥러닝의 기본 틀입니다.
자기점검 체크리스트
- 퍼셉트론의 수식 $z = w_1 x_1 + w_2 x_2 + b$와 계단 함수의 역할을 설명할 수 있다
- NumPy로 AND, OR, NAND 게이트를 구현할 수 있다
- 가중치와 편향을 바꿨을 때 결정 경계 직선이 어떻게 움직이는지 설명할 수 있다
- XOR이 단층 퍼셉트론으로 풀리지 않는 이유를 기하학적으로 말할 수 있다
- “뉴런을 코드로 흉내 내면 무엇을 할 수 있고 없는가”에 자기 말로 답할 수 있다
🧠 인터랙티브 퀴즈
섹션 제목: “🧠 인터랙티브 퀴즈”퍼셉트론에서 활성화 함수(계단 함수)가 하는 일은 무엇입니까?
AND 게이트에서 가중치는 그대로 두고 편향 b만 -0.7에서 -0.2로 바꾸면 어떤 게이트가 됩니까?
2D 평면에서 퍼셉트론의 결정 경계는 어떤 형태입니까?
XOR 문제를 해결하려면 어떻게 해야 합니까?
💭 성찰
섹션 제목: “💭 성찰”아래 질문에 한두 문장씩 답을 적어봅니다.
- 오늘 배운 개념 중에서 가장 인상 깊었던 것은 무엇이며, 그 이유는 무엇입니까?
- 단층 퍼셉트론이 XOR에서 실패하는 장면을 직접 겪은 후, “인공지능의 한계”에 대한 내 생각이 어떻게 바뀌었습니까?
- 아직 완전히 이해되지 않은 부분이 있다면 어디이며, 무엇을 더 알아보고 싶습니까?
- 오늘 만든 퍼셉트론 코드는 단 10줄 남짓입니다. 이렇게 단순한 장치가 현대 AI의 뿌리라는 사실에서 어떤 인사이트를 얻었습니까?
🔗 다음 차시 미리보기
섹션 제목: “🔗 다음 차시 미리보기”5차시에서는 오늘 만난 XOR의 벽을 직접 무너뜨립니다. 퍼셉트론 여러 개를 층층이 쌓은 다층 퍼셉트론(MLP) 을 구현하고, 계단 함수 대신 시그모이드·ReLU를 쓰는 이유를 다룹니다. 그리고 가장 중요한 질문 하나를 던집니다.
“가중치를 일일이 손으로 설정했는데, 컴퓨터가 스스로 올바른 가중치를 찾게 하려면 어떻게 해야 할까요?”
이 질문의 답이 바로 ‘학습’입니다.