
학습 내용
미분의 기초
학습 목표
이 레슨을 완료하면:
- •미분이 "변화율"이라는 것을 일상 비유로 설명할 수 있습니다
- •기본 미분 공식을 적용하고 Python으로 검증할 수 있습니다
- •함수와 도함수를 나란히 그래프로 그릴 수 있습니다
- •경사하강법의 원리를 이해하고 Python으로 직접 시뮬레이션할 수 있습니다
- •학습률이 학습에 미치는 영향을 시각적으로 확인할 수 있습니다
핵심 메시지
"미분을 이해하면 AI가 어떻게 스스로 학습하는지 알 수 있습니다!" 미분은 "지금 이 순간 얼마나 빠르게 변하고 있는가"를 알려주는 도구이고, AI는 이것을 사용해서 스스로 똑똑해집니다.
1. 미분이란? - 변화율 이야기
비유: 자동차 속도계
고속도로에서 자동차를 운전한다고 상상해보세요.
- •위치: 내가 지금 어디에 있는가 (서울에서 100km 지점)
- •속도: 위치가 얼마나 빠르게 변하고 있는가 (시속 80km)
속도는 위치의 변화율입니다. 그리고 이 변화율을 구하는 것이 바로 미분입니다!
| 일상 용어 | 수학 용어 | 의미 |
|---|---|---|
| 위치 | 함수 f(x) | 현재 상태 |
| 속도 | 도함수 f'(x) | 변화율 (미분한 결과) |
| "지금 얼마나 빠른가?" | "이 점에서 기울기는?" | 같은 질문! |
더 쉽게 말하면:
- •온도가 올라가는 중이면 → 변화율은 양수 (+)
- •온도가 내려가는 중이면 → 변화율은 음수 (-)
- •온도가 안 변하면 → 변화율은 0
접선의 기울기 = 미분값
곡선 위의 한 점에 자를 대면 접선(살짝 닿는 직선)을 그릴 수 있습니다. 이 접선의 기울기가 바로 그 점에서의 미분값입니다.
| 접선의 기울기 | 의미 | 함수 상태 |
|---|---|---|
| 양수 (+) | 오른쪽 위로 올라감 | 증가하는 중 |
| 음수 (-) | 오른쪽 아래로 내려감 | 감소하는 중 |
| 0 | 수평 (평평함) | 꼭대기 또는 바닥! |
실행해보기: 미분의 의미를 눈으로 확인
pythonimport numpy as np import matplotlib.pyplot as plt # 함수: f(x) = x^2 def f(x): return x ** 2 x = np.linspace(-3, 3, 200) y = f(x) plt.figure(figsize=(8, 6)) plt.plot(x, y, 'b-', linewidth=2, label='f(x) = x^2') # 세 점에서의 접선 그리기 points = [-2, 0, 1.5] colors = ['red', 'green', 'orange'] for pt, color in zip(points, colors): slope = 2 * pt # f'(x) = 2x y_pt = f(pt) # 접선: y - y_pt = slope * (x - pt) x_tan = np.linspace(pt - 1.5, pt + 1.5, 50) y_tan = slope * (x_tan - pt) + y_pt plt.plot(x_tan, y_tan, '--', color=color, linewidth=2, label=f'tangent at x={pt} (slope={slope})') plt.plot(pt, y_pt, 'o', color=color, markersize=8) plt.axhline(y=0, color='gray', linewidth=0.5) plt.axvline(x=0, color='gray', linewidth=0.5) plt.ylim(-2, 10) plt.xlabel('x') plt.ylabel('f(x)') plt.title('Derivative = Tangent Line Slope') plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() plt.show() print('tangent slope at each point:') print(f' x=-2: slope = 2*(-2) = -4 (decreasing)') print(f' x= 0: slope = 2*( 0) = 0 (minimum!)') print(f' x=1.5: slope = 2*(1.5)= 3 (increasing)')
2. 기본 미분 공식
미분에는 규칙이 있습니다. 모든 것을 외울 필요 없이 핵심 패턴만 알면 됩니다.
핵심 미분 규칙
| 원래 함수 f(x) | 미분 결과 f'(x) | 예시 |
|---|---|---|
| x^n | n * x^(n-1) | x^3 -> 3x^2 |
| x^2 | 2x | x=3일 때 기울기=6 |
| x | 1 | 항상 기울기 1 (직선) |
| 상수 (예: 5) | 0 | 변하지 않으므로 변화율 0 |
| e^x | e^x (자기 자신!) | 미분해도 변하지 않는 신기한 함수 |
| a * f(x) | a * f'(x) | 3x^2 -> 3*2x = 6x |
가장 중요한 규칙: x^n을 미분하면 지수를 앞으로 내리고, 지수를 1 줄인다
실행해보기: 수치 미분으로 검증하기
수학 공식 없이도, 아주 작은 간격으로 기울기를 계산하면 미분값을 구할 수 있습니다. 이것을 수치 미분이라고 합니다.
pythonimport numpy as np def f(x): return x ** 2 def numerical_derivative(f, x, h=0.0001): """아주 작은 간격 h로 기울기를 구합니다""" return (f(x + h) - f(x - h)) / (2 * h) print('f(x) = x^2 numerical vs analytical derivative:') print(f'{"x":>5} | {"numerical f(x)":>18} | {"analytical 2x":>16} | {"match?":>8}') print('-' * 60) for x_val in [-3, -2, -1, 0, 1, 2, 3]: num = numerical_derivative(f, x_val) ana = 2 * x_val match = 'O' if abs(num - ana) < 0.001 else 'X' print(f'{x_val:5.1f} | {num:18.6f} | {ana:16.6f} | {match:>8}') print() print('numerical derivative is useful because:') print(' - no formula needed (just compute slope)') print(' - works with any function') print(' - this is how computers calculate derivatives!')
3. 함수와 도함수를 나란히 보기
함수 f(x)와 그 미분인 f'(x)를 나란히 그리면, 미분의 의미가 직관적으로 이해됩니다.
실행해보기: f(x) = x^3 - 3x 와 도함수
pythonimport numpy as np import matplotlib.pyplot as plt x = np.linspace(-2.5, 2.5, 200) # 원래 함수와 도함수 f = x**3 - 3*x # f(x) = x^3 - 3x f_prime = 3*x**2 - 3 # f'(x) = 3x^2 - 3 fig, axes = plt.subplots(2, 1, figsize=(8, 8), sharex=True) # 위: 원래 함수 axes[0].plot(x, f, 'b-', linewidth=2) axes[0].axhline(y=0, color='gray', linewidth=0.5) axes[0].set_ylabel('f(x)') axes[0].set_title('Original: f(x) = x^3 - 3x') axes[0].grid(True, alpha=0.3) # 극값 표시 axes[0].plot(-1, 2, 'ro', markersize=10) axes[0].plot(1, -2, 'ro', markersize=10) axes[0].annotate('local max', xy=(-1, 2), xytext=(-2, 3), arrowprops=dict(arrowstyle='->'), fontsize=11) axes[0].annotate('local min', xy=(1, -2), xytext=(2, -3), arrowprops=dict(arrowstyle='->'), fontsize=11) # 아래: 도함수 axes[1].plot(x, f_prime, 'r-', linewidth=2) axes[1].axhline(y=0, color='gray', linewidth=0.5) axes[1].fill_between(x, f_prime, 0, where=(f_prime > 0), alpha=0.1, color="green", label="f'(x)>0: increasing") axes[1].fill_between(x, f_prime, 0, where=(f_prime < 0), alpha=0.1, color="red", label="f'(x)<0: decreasing") axes[1].set_xlabel("x") axes[1].set_ylabel("f'(x)") axes[1].set_title("Derivative: f'(x) = 3x^2 - 3") axes[1].legend() axes[1].grid(True, alpha=0.3) # 도함수=0인 점 표시 axes[1].plot([-1, 1], [0, 0], 'ro', markersize=10) axes[1].annotate('slope=0\n(extremum!)', xy=(-1, 0), xytext=(-2, 5), arrowprops=dict(arrowstyle='->'), fontsize=10) plt.tight_layout() plt.show() print("Key observations:") print(" - Where f'(x) = 0 -> f(x) has max or min") print(" - Where f'(x) > 0 -> f(x) is going up") print(" - Where f'(x) < 0 -> f(x) is going down")
핵심: 도함수가 0인 지점이 바로 원래 함수의 최댓값 또는 최솟값입니다. AI는 이 성질을 이용해서 손실이 최소인 지점을 찾습니다!
4. 경사하강법: AI가 학습하는 원리
비유: 눈을 가리고 산에서 내려오기
당신이 눈을 가린 채 산꼭대기에 있다고 상상해보세요. 가장 낮은 곳(계곡)까지 내려가야 합니다.
어떻게 할까요?
- •발로 바닥을 더듬어 어느 쪽이 내리막인지 느낀다 (= 기울기 계산 = 미분!)
- •내리막 방향으로 한 발짝 이동한다 (= 기울기 반대 방향으로 이동)
- •반복한다 (= 여러 번의 학습 step)
이것이 바로 **경사하강법(Gradient Descent)**입니다!
핵심 공식
w_new = w_old - learning_rate * gradient
| 요소 | 의미 | 산 비유 |
|---|---|---|
| w (가중치) | AI가 학습하는 값 | 현재 위치 |
| learning_rate (학습률) | 한 번에 얼마나 이동? | 발걸음 크기 |
| gradient (기울기) | 미분으로 계산한 방향 | 바닥을 더듬은 결과 |
| - (마이너스) | 반대 방향으로! | 내리막으로 가기 위해 |
🔬 실습: 경사하강법 단계별 시뮬레이션
AI가 실제로 어떻게 학습하는지 단계별로 확인해봅시다.
pythonimport numpy as np import matplotlib.pyplot as plt # ═══════════════════════════════════════════════════════════════ # 📊 경사하강법(Gradient Descent) 시뮬레이션 # 목표: 손실 함수의 최솟값(w=0)을 찾아가기 # ═══════════════════════════════════════════════════════════════ # 📐 손실 함수 정의: L(w) = w² (포물선 모양) # 최솟값은 w=0일 때 Loss=0 def loss(w): return w ** 2 def loss_gradient(w): return 2 * w # 📝 미분: dL/dw = 2w # ───────────────────────────────────────────────────────────────── # 🚀 경사하강법 실행 # ───────────────────────────────────────────────────────────────── w = 4.0 # 🎯 시작 위치 (산 중턱) learning_rate = 0.15 # 👣 발걸음 크기 history = [w] print("🏔️ 경사하강법 시뮬레이션 - 손실 최솟값 찾아가기") print("=" * 65) print(f'{"Step":>4} | {"위치(w)":>10} | {"손실":>10} | {"기울기":>10} | {"이동량":>10}') print("-" * 65) for step in range(15): grad = loss_gradient(w) # 📐 현재 위치의 기울기 계산 update = learning_rate * grad # 👣 이동할 거리 계산 print(f'{step:4d} | {w:10.4f} | {loss(w):10.4f} | {grad:10.4f} | {-update:10.4f}') w = w - update # ⬇️ 기울기 반대 방향으로 이동! history.append(w) print("-" * 65) print(f'{"완료":>4} | {w:10.4f} | {loss(w):10.4f} | 🎉 최솟값 도달!') # ───────────────────────────────────────────────────────────────── # 📈 시각화: 학습 과정을 그래프로 확인 # ───────────────────────────────────────────────────────────────── fig, axes = plt.subplots(1, 2, figsize=(14, 5)) # 📊 왼쪽 그래프: 손실 곡선 위의 이동 경로 w_range = np.linspace(-5, 5, 200) axes[0].plot(w_range, loss(w_range), 'b-', linewidth=2, label='Loss function L(w) = w²') history_arr = np.array(history) axes[0].plot(history_arr, loss(history_arr), 'ro-', markersize=8, label='Learning path') axes[0].plot(history_arr[0], loss(history_arr[0]), 'g*', markersize=20, label='Start point') axes[0].plot(0, 0, 'b*', markersize=15, label='Target (minimum)') axes[0].set_xlabel('Weight w', fontsize=12) axes[0].set_ylabel('Loss', fontsize=12) axes[0].set_title('Loss Curve: Descending to Minimum', fontsize=14) axes[0].legend(fontsize=10) axes[0].grid(True, alpha=0.3) # 📊 오른쪽 그래프: 학습 단계별 손실 감소 loss_history = [loss(w) for w in history] axes[1].plot(range(len(history)), loss_history, 'r-o', markersize=6, linewidth=2) axes[1].fill_between(range(len(history)), loss_history, alpha=0.3, color='red') axes[1].set_xlabel('Training Step', fontsize=12) axes[1].set_ylabel('Loss', fontsize=12) axes[1].set_title('Loss Decreases During Training', fontsize=14) axes[1].grid(True, alpha=0.3) plt.tight_layout() plt.show()
💡 핵심 포인트: w가 점점 0에 가까워지고, 손실도 점점 줄어듭니다!
- •왼쪽 그래프: 산을 내려오듯이 최솟값으로 이동
- •오른쪽 그래프: 학습할수록 손실(오차)가 감소
이것이 바로 AI가 학습하는 원리입니다!
5. 학습률의 중요성
학습률(learning rate)은 한 번에 얼마나 크게 이동할지를 결정합니다. 이 값을 잘 설정하는 것이 매우 중요합니다.
| 학습률 | 결과 | 산 비유 |
|---|---|---|
| 너무 크면 | 최솟값을 지나쳐서 발산 | 점프가 너무 커서 계곡을 넘어감 |
| 너무 작으면 | 수렴은 하지만 너무 느림 | 한 발짝이 너무 작아서 평생 걸림 |
| 적당하면 | 빠르고 안정적으로 수렴 | 적당한 걸음으로 계곡 도착! |
실행해보기: 학습률 비교 (너무 큼 vs 적당함 vs 너무 작음)
pythonimport numpy as np import matplotlib.pyplot as plt def loss(w): return w ** 2 def gradient(w): return 2 * w def run_gradient_descent(start_w, lr, steps): w = start_w history = [w] for _ in range(steps): w = w - lr * gradient(w) history.append(w) return history start_w = 4.0 steps = 20 # 세 가지 학습률 configs = [ (0.01, 'too small (lr=0.01)', 'blue'), (0.15, 'just right (lr=0.15)', 'green'), (0.9, 'too large (lr=0.9)', 'red'), ] fig, axes = plt.subplots(1, 3, figsize=(15, 5)) for idx, (lr, label, color) in enumerate(configs): history = run_gradient_descent(start_w, lr, steps) # 손실 함수 곡선 w_range = np.linspace(-6, 6, 200) axes[idx].plot(w_range, loss(w_range), 'gray', linewidth=1, alpha=0.5) # 이동 경로 h = np.array(history[:steps+1]) axes[idx].plot(h, loss(h), 'o-', color=color, markersize=5, linewidth=1.5) axes[idx].plot(h[0], loss(h[0]), 'k*', markersize=12) axes[idx].set_title(label, fontsize=13, fontweight='bold') axes[idx].set_xlabel('w') axes[idx].set_ylabel('Loss') axes[idx].set_ylim(-2, 30) axes[idx].grid(True, alpha=0.3) final_loss = loss(history[-1]) axes[idx].text(0.05, 0.95, f'final loss={final_loss:.4f}', transform=axes[idx].transAxes, fontsize=10, verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5)) plt.suptitle('Learning Rate Comparison', fontsize=14, fontweight='bold') plt.tight_layout() plt.show() print('Summary:') for lr, label, _ in configs: h = run_gradient_descent(start_w, lr, steps) print(f' {label}: final w={h[-1]:.6f}, final loss={loss(h[-1]):.6f}')
학습률 0.9는 최솟값 주위를 왔다갔다하면서 불안정합니다. 0.01은 안정적이지만 너무 느립니다. 0.15가 빠르면서도 안정적으로 수렴합니다. 실제 딥러닝에서는 보통 0.001 ~ 0.01 범위에서 시작합니다.
6. 더 복잡한 함수에서의 경사하강법
실제 AI의 손실 함수는 단순한 w^2가 아니라 울퉁불퉁한 모양입니다. 그래도 원리는 동일합니다.
실행해보기: 울퉁불퉁한 손실 함수에서의 경사하강법
pythonimport numpy as np import matplotlib.pyplot as plt # 좀 더 복잡한 손실 함수 def complex_loss(w): return w**4 - 8*w**2 + 2*w + 20 def complex_gradient(w): return 4*w**3 - 16*w + 2 # derivative w = -3.5 # 시작점 lr = 0.01 history = [(w, complex_loss(w))] for _ in range(100): grad = complex_gradient(w) w = w - lr * grad history.append((w, complex_loss(w))) history = np.array(history) plt.figure(figsize=(10, 5)) w_range = np.linspace(-4, 4, 300) plt.plot(w_range, complex_loss(w_range), 'b-', linewidth=2, label='Loss function') plt.plot(history[:, 0], history[:, 1], 'ro-', markersize=3, alpha=0.7, label='GD path') plt.plot(history[0, 0], history[0, 1], 'g*', markersize=15, label='start') plt.plot(history[-1, 0], history[-1, 1], 'r*', markersize=15, label='end') plt.xlabel('w') plt.ylabel('Loss') plt.title('Gradient Descent on Complex Loss') plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() plt.show() print(f'Start: w={history[0,0]:.2f}, loss={history[0,1]:.2f}') print(f'End: w={history[-1,0]:.4f}, loss={history[-1,1]:.4f}') print() print('Note: depending on start, GD may find a LOCAL minimum,') print('not the GLOBAL minimum. This is a real challenge in AI!')
AI와의 연결: 신경망의 손실 함수에는 수많은 "지역 최솟값(local minimum)"이 있습니다. 시작점에 따라 다른 결과가 나올 수 있어요. 이것이 딥러닝에서 가중치 초기화와 학습률이 중요한 이유입니다.
7. 왜 이것이 중요한가? - AI 학습의 전체 그림
지금까지 배운 것을 종합하면:
- •신경망은 입력을 받아 예측을 출력하는 거대한 함수입니다
- •손실 함수가 예측이 얼마나 틀렸는지 알려줍니다 (2차함수처럼 생겼어요)
- •미분으로 손실 함수의 기울기를 구합니다
- •경사하강법으로 기울기 반대 방향으로 가중치를 업데이트합니다
- •학습률이 한 번에 얼마나 움직일지 결정합니다
- •이 과정을 수천~수만 번 반복하면 → AI가 점점 똑똑해집니다!
이것이 바로 모든 AI 학습의 핵심 원리입니다.
핵심 요약
| 개념 | 설명 | AI에서의 역할 |
|---|---|---|
| 미분 | 변화율 (접선의 기울기) | 손실 함수의 기울기 계산 |
| 수치 미분 | 작은 간격으로 기울기 근사 | 컴퓨터가 미분을 계산하는 방법 |
| 도함수 | 미분 결과 함수 | 기울기가 0인 곳 = 극값 |
| 경사하강법 | 기울기 반대 방향으로 이동 | AI 학습의 핵심 알고리즘 |
| 학습률 | 이동 크기 결정 | 너무 크면 발산, 너무 작으면 느림 |
학습 체크리스트
- • 미분이 "변화율"이라는 것을 자동차 속도 비유로 설명할 수 있다
- • x^2를 미분하면 2x, x^3를 미분하면 3x^2임을 안다
- • 수치 미분의 원리를 이해하고 Python으로 구현할 수 있다
- • 경사하강법이 왜 기울기의 "반대" 방향으로 이동하는지 설명할 수 있다
- • 학습률이 너무 크거나 작으면 어떤 문제가 생기는지 시각적으로 확인했다
- • w = w - learning_rate * gradient 공식을 이해한다
다음 강의 예고
"편미분" - 변수가 여러 개일 때 각각에 대해 미분하는 방법! 신경망의 수백만 파라미터를 동시에 학습시키는 핵심입니다.
레슨 정보
- 레벨
- Level 2: 수학 기초
- 예상 소요 시간
- 4분 30초
- 참고 영상
- YouTube 링크
💡실습 환경 안내
코드 블록의 ▶ 실행 버튼을 누르면 브라우저에서 바로 Python을 실행할 수 있습니다.
별도 설치 없이 NumPy, Matplotlib 등 기본 라이브러리를 사용할 수 있습니다.