← 강의 목록

Lecture 9. 선형 회귀

데이터 점들에 가장 잘 맞는 직선(또는 곡선)을 찾는 것 — 머신러닝의 첫걸음.

목차

  1. 회귀 분석이란
  2. 최소제곱법
  3. 정규방정식
  4. 다항 회귀와 과적합
  5. 인터랙티브 데모

1. 회귀란?

입력 $x$와 출력 $y$의 관계를 함수 $y = f(x)$로 추정하는 작업입니다. 가장 단순한 가설은 직선:

$$ y = \beta_0 + \beta_1 x + \varepsilon $$

$\varepsilon$은 데이터에 섞인 잡음입니다.

2. 최소제곱법 (Least Squares)

"가장 잘 맞는" 직선이란 모든 점에서 직선까지 수직 거리(잔차)의 제곱합이 최소인 직선입니다.

$$ \text{minimize}\;\; \sum_{i=1}^n \bigl(y_i - (\beta_0 + \beta_1 x_i)\bigr)^2 $$

3. 정규방정식 (행렬 형태)

데이터를 행렬 $X$, 출력을 벡터 $y$로 쌓으면 한 번에 해를 구할 수 있습니다.

$$ \boldsymbol{\beta} = (X^\top X)^{-1} X^\top y $$

이 식 하나가 19세기 통계학에서 21세기 딥러닝까지 모든 것의 출발점입니다.

4. L2 vs L1 손실, 그리고 Huber

$$ L_2 = \sum_i (y_i - \hat y_i)^2 \qquad L_1 = \sum_i |y_i - \hat y_i| $$

🎮 인터랙티브: L1 회귀 vs L2 회귀 (이상치에 대한 강건성)

같은 데이터에 L2(파랑)과 L1(주황) 회귀 직선을 동시에 적합합니다. "이상치 강도" 슬라이더를 키우면 한 점의 y값이 크게 튀고, L2 직선만 크게 휘는 것을 볼 수 있습니다. 이것이 L1이 이상치에 강건한 이유입니다.

5. 다항 회귀와 과적합

$y = \beta_0 + \beta_1 x + \beta_2 x^2 + \dots + \beta_d x^d$로 차수를 올리면 더 잘 맞춥니다. 하지만 차수가 너무 높으면 학습 데이터의 잡음까지 외워버리는 과적합이 발생합니다.

🎮 인터랙티브: 다항 회귀와 과적합

점을 클릭해 추가/제거하고, 차수를 바꿔가며 곡선이 어떻게 변하는지 관찰하세요.

왼쪽 클릭: 점 추가 · 오른쪽 클릭: 점 제거

차수를 1로 두면 직선, 9까지 올리면 모든 점을 지나는 구불구불한 곡선이 됩니다. 그게 바로 과적합입니다.

6. Ridge 정규화 — 과적합 길들이기

고차 다항 회귀의 과적합을 다루는 가장 단순한 방법은 계수의 크기에도 벌점을 주는 것입니다. L2 벌점을 추가하면 Ridge 회귀가 됩니다:

$$ \boldsymbol{\beta}_\text{ridge} = \arg\min_\beta \|y - X\beta\|^2 + \lambda \|\beta\|^2 = (X^\top X + \lambda I)^{-1} X^\top y $$

$\lambda$가 클수록 계수가 작아지고 곡선이 더 매끄러워집니다. L1 벌점을 쓰면 Lasso가 되고, 일부 계수가 정확히 0이 되어 자동 변수 선택 효과가 납니다.

🎮 인터랙티브: Ridge λ 효과

9점으로 9차 다항식(파라미터 10개)을 맞추면 $\lambda=0$에서 심한 과적합이 일어납니다. 슬라이더를 오른쪽으로 옮겨 $\lambda$를 키우면 곡선이 점점 매끄러워지다가 결국 평균선에 가까워집니다.

7. 경사하강법 (Gradient Descent)

$X^\top X$의 역을 구하기 어려운 큰 문제(수만 개의 특징)에서는 반복적 최적화를 씁니다. MSE의 기울기를 따라 조금씩 내려갑니다:

$$ \beta \leftarrow \beta - \eta\, \nabla_\beta L = \beta - \eta \cdot \tfrac{2}{n} X^\top (X\beta - y) $$

$\eta$(학습률)가 너무 크면 발산, 너무 작으면 수렴이 느립니다. 딥러닝의 모든 훈련도 결국 이 식의 변형입니다.

🎮 인터랙티브: 1차 회귀의 경사하강법

왼쪽: 데이터와 현재 직선. 오른쪽: MSE 손실 표면($\beta_0, \beta_1$)에서 내려가는 궤적. Step을 누를 때마다 한 번 업데이트됩니다.

8. 코드 예제 (Python)

import numpy as np
import matplotlib.pyplot as plt

# 가짜 데이터
x = np.linspace(0, 10, 30)
y = 2*x + 1 + np.random.randn(30)*2

# numpy 한 줄
beta = np.polyfit(x, y, deg=1)    # [β1, β0]
print(beta)

# 직접 정규방정식
X = np.column_stack([np.ones_like(x), x])
beta2 = np.linalg.inv(X.T @ X) @ X.T @ y
print(beta2)

plt.scatter(x, y); plt.plot(x, np.polyval(beta, x)); plt.show()

9. 더 깊이 공부하기