← 강의 홈으로
기계학습 2026 · 실습

실습 안내

강의에서 배운 핵심 알고리즘을 직접 구현해 봅니다. 총 2개의 실습이 있으며 모두 Jupyter 노트북으로 진행합니다.

실습 1 · 경사하강법 실습 2 · 신경망
📈 실습 1 · 경사하강법으로 선형회귀 학습
범위: 2 ~ 3주차도구: NumPy, matplotlib

주택 면적으로 가격을 예측하는 선형회귀 모델 f(x) = wx + b를 경사하강법으로 학습합니다.

PYTHON · 데이터
import numpy as np
rng = np.random.default_rng(0)
x = rng.uniform(0.5, 3.5, 50)              # 면적 (1000 feet²)
y = 100 * x + 50 + rng.normal(0, 20, 50)   # 가격 ($1000)
  • 비용함수 compute_cost(x, y, w, b): J(w,b) = (1/2m) Σ (wx⁽ⁱ⁾ + b − y⁽ⁱ⁾)²
  • 경사하강법 gradient_descent(x, y, alpha, iters): w와 b를 동시 갱신합니다.
  • α = 0.1로 1000번 학습한 뒤 학습 곡선(J 대 반복 횟수)을 그리고, 1250 feet² 주택의 가격을 예측합니다.
정답 코드 보기
PYTHON · 정답 (데이터 코드 다음에 실행)
import matplotlib.pyplot as plt

def compute_cost(x, y, w, b):
    m = x.shape[0]
    f = w * x + b                          # 예측값
    return np.sum((f - y) ** 2) / (2 * m)  # 제곱오차의 평균의 절반

def gradient_descent(x, y, alpha, iters, w=0.0, b=0.0):
    m = x.shape[0]
    J_hist = []
    for _ in range(iters):
        err = w * x + b - y
        dj_dw = np.sum(err * x) / m                     # 이전 w, b로 두 기울기를 먼저 계산
        dj_db = np.sum(err) / m
        w, b = w - alpha * dj_dw, b - alpha * dj_db     # 동시 갱신
        J_hist.append(compute_cost(x, y, w, b))
    return w, b, J_hist

w, b, J_hist = gradient_descent(x, y, alpha=0.1, iters=1000)
print(f"w = {w:.2f}, b = {b:.2f}")
print(f"1250 feet² 예측 가격: ${(w * 1.25 + b) * 1000:,.0f}")

plt.plot(J_hist)
plt.xlabel("iteration"); plt.ylabel("J(w, b)"); plt.title("learning curve")
plt.show()

실행 결과

w = 103.49, b = 43.40
1250 feet² 예측 가격: $172,766

해설: 학습된 w ≈ 103, b ≈ 43은 데이터를 만든 값(100, 50)에 가깝습니다. 학습 곡선은 처음에 빠르게 내려간 뒤 평평해지며, 이는 경사하강법이 수렴했다는 뜻입니다.

🧠 실습 2 · TensorFlow로 손글씨 숫자 분류
범위: 7 ~ 10주차도구: TensorFlow, scikit-learn

8×8 손글씨 숫자 이미지(0~9)를 분류하는 신경망을 학습합니다.

PYTHON · 시작 코드
import numpy as np
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.losses import SparseCategoricalCrossentropy

X, y = load_digits(return_X_y=True)          # 8×8 = 64 픽셀, 숫자 0~9
X = X / 16.0
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
  • 25(ReLU) → 15(ReLU) → 10(linear) 구조의 모델을 만들고, SparseCategoricalCrossentropy(from_logits=True)와 Adam(learning_rate = 0.001)으로 30 epoch 학습합니다.
  • 테스트 정확도를 출력하고, 테스트 이미지 하나에 대해 tf.nn.softmax로 클래스별 확률과 예측한 숫자를 출력합니다.
정답 코드 보기
PYTHON · 정답 (시작 코드 다음에 실행)
tf.keras.utils.set_random_seed(0)            # 재현성

model = Sequential([
    Dense(25, activation="relu"),
    Dense(15, activation="relu"),
    Dense(10, activation="linear"),          # 출력은 logits
])
model.compile(loss=SparseCategoricalCrossentropy(from_logits=True),
              optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),
              metrics=["accuracy"])
model.fit(X_train, y_train, epochs=30, verbose=0)

loss, acc = model.evaluate(X_test, y_test, verbose=0)
print(f"테스트 정확도: {acc:.3f}")

# 출력층은 logits(z)를 내므로, 확률은 softmax를 직접 적용해 얻는다
logits = model.predict(X_test[:1], verbose=0)
probs = tf.nn.softmax(logits).numpy()
print("확률:", np.round(probs, 3))
print("예측:", probs.argmax(), "정답:", y_test[0])

실행 결과 (TensorFlow 버전·환경에 따라 정확도가 조금 다를 수 있습니다)

테스트 정확도: 0.956
확률: [[0.    0.    0.999 0.001 0.    0.    0.    0.    0.    0.   ]]
예측: 2 정답: 2

해설: 출력층을 "linear"로 두고 from_logits=True를 쓰면, TensorFlow가 소프트맥스와 log를 손실 안에서 한 번에 계산해 수치 오차를 줄입니다. 그래서 모델 출력은 확률이 아닌 logits이며, 확률이 필요하면 tf.nn.softmax를 적용합니다.