Chapter 21: 분류 말고 회귀 - 숫자 예측하기¶
한 줄 요약: 분류가 "무엇인가?"를 맞추는 거라면, 회귀는 "얼마인가?"를 예측하는 것입니다.
🎯 이 장에서 배우는 것¶
- [ ] 분류와 회귀의 차이를 명확히 구분할 수 있다
- [ ] 회귀 모델로 연속적인 숫자를 예측할 수 있다
- [ ] MAE, RMSE 등 회귀 평가 지표를 이해하고 계산할 수 있다
- [ ] 예측값과 실제값을 비교하는 시각화를 만들 수 있다
💡 왜 이걸 배우나요?¶
세상의 절반은 "얼마?"라는 질문이다¶
지금까지 분류를 배웠어. "스팸일까 아닐까?", "고양이일까 강아지일까?" 같은 카테고리를 맞추는 문제였지.
하지만 세상의 많은 질문은 숫자로 답해야 해:
"이 집 가격이 얼마야?" → 3억 2천만원
"내일 기온이 몇 도야?" → 24.5도
"이 영상 조회수가 얼마나 될까?" → 15만 뷰
"배달 도착까지 몇 분 걸려?" → 32분
"이 주식 내일 가격이 얼마야?" → 52,300원
분류는 정해진 선택지 중에 고르는 거고, 회귀는 무한한 숫자 중에서 정확한 값을 예측하는 거야.
이미 경험해본 회귀¶
사실 너도 이미 회귀를 경험했어:
- 시험 점수 예상: "이 정도 공부했으면... 85점쯤?"
- 도착 시간 계산: "거기까지 지하철로... 40분쯤?"
- 가격 짐작: "이런 카페에서 아메리카노는... 4,500원쯤?"
과거 데이터와 경험을 바탕으로 숫자를 예측하는 게 바로 회귀야. 이제 컴퓨터가 이걸 더 정확하게 하도록 만들어보자!
📚 핵심 개념¶
개념 1: 분류 vs 회귀¶
비유로 시작 🎯
분류와 회귀는 마치 객관식 vs 주관식 같아요.
[객관식 - 분류]
Q: 이 동물은 무엇인가요?
① 고양이 ② 강아지 ③ 토끼 ④ 햄스터
[주관식 - 회귀]
Q: 이 집의 가격은 얼마인가요?
___________ 원
객관식은 정해진 보기 중에서 고르고, 주관식은 정확한 숫자를 직접 써야 해.
정확히 말하면: - 분류(Classification): 데이터를 정해진 범주 중 하나로 분류 - 회귀(Regression): 연속적인 숫자를 예측
예시로 확인:
| 질문 | 분류? 회귀? | 이유 |
|---|---|---|
| 이 메일이 스팸인가? | 분류 | "스팸/정상" 둘 중 하나 |
| 이 집 가격이 얼마? | 회귀 | 1억~100억 사이 어떤 숫자든 가능 |
| 이 학생이 합격할까? | 분류 | "합격/불합격" 둘 중 하나 |
| 이 학생 점수가 몇 점? | 회귀 | 0~100 사이 어떤 숫자든 가능 |
| 이 영화가 어떤 장르? | 분류 | "액션/로맨스/공포" 등 정해진 장르 |
| 이 영화 평점이 몇 점? | 회귀 | 1.0~10.0 사이 어떤 숫자든 가능 |
쉽게 말하면: 정해진 칸 중에 고르면 분류, 숫자를 직접 예측하면 회귀!
개념 2: 회귀는 "최적의 선 긋기"¶
비유로 시작 📏
회귀는 마치 데이터 점들 사이로 가장 잘 맞는 선을 긋는 것과 같아요.
가격(만원)
│
500┤ ★ ← 실제 데이터
400┤ ★ /
300┤ ★ /
200┤ ★ /
100┤ ★ / ← 이 선이 예측선!
│___/______________________
20 40 60 80 100 면적(㎡)
작은 집은 싸고, 큰 집은 비싸다는 패턴이 보이지? 이 패턴을 선(함수)으로 표현해서 새 데이터를 예측하는 거야.
정확히 말하면: 회귀 모델은 입력(X)과 출력(Y) 사이의 관계(함수)를 학습해. 가장 단순한 형태가 선형 회귀(Linear Regression):
Y = aX + b
가격 = (기울기) × 면적 + (기본값)
= 5만원/㎡ × 면적 + 50만원
예시로 확인:
# 만약 기울기가 5, 기본값이 50이라면
# 30㎡ 집의 예상 가격 = 5 × 30 + 50 = 200만원
# 80㎡ 집의 예상 가격 = 5 × 80 + 50 = 450만원
쉽게 말하면: 회귀는 데이터의 패턴을 수식으로 표현하는 것!
개념 3: 회귀 평가 지표 - "얼마나 틀렸나?"¶
비유로 시작 🎯
분류에서는 "맞았다/틀렸다"로 평가했지? 회귀에서는 "얼마나 틀렸나"로 평가해.
[분류 - 이진적]
정답: 고양이
예측: 강아지
결과: 틀림 ❌
[회귀 - 정도의 문제]
정답: 300만원
예측: 280만원
결과: 20만원 차이 (꽤 가까움!)
정답: 300만원
예측: 100만원
결과: 200만원 차이 (많이 틀림!)
정확히 말하면, 회귀의 대표적인 평가 지표 3가지:
1. MAE (Mean Absolute Error) - 평균 절대 오차
MAE = |오차들|의 평균
예) 실제값: [100, 200, 300]
예측값: [90, 220, 280]
오차: [-10, +20, -20]
절대값: [10, 20, 20]
MAE = (10 + 20 + 20) / 3 = 16.67
→ 해석: "평균적으로 16.67만큼 틀린다"
2. MSE (Mean Squared Error) - 평균 제곱 오차
MSE = (오차²)들의 평균
예) 오차: [-10, +20, -20]
제곱: [100, 400, 400]
MSE = (100 + 400 + 400) / 3 = 300
→ 특징: 큰 오차에 더 큰 페널티 (제곱하니까)
3. RMSE (Root Mean Squared Error) - 평균 제곱근 오차
RMSE = √MSE = √300 ≈ 17.32
→ 해석: MSE에 루트를 씌워서 원래 단위로 돌려놓음
비교 정리:
┌─────────┬───────────────────────────────────┐
│ 지표 │ 특징 │
├─────────┼───────────────────────────────────┤
│ MAE │ 직관적, 이상치에 덜 민감 │
│ MSE │ 큰 오차에 더 민감 (제곱 효과) │
│ RMSE │ MSE의 해석 가능한 버전 │
└─────────┴───────────────────────────────────┘
쉽게 말하면: MAE는 "평균적으로 얼마나 틀렸나", RMSE는 "큰 실수를 더 심하게 벌주는 버전"!
개념 4: R² 스코어 - "얼마나 잘 설명하나?"¶
비유로 시작 📊
R²는 마치 시험에서 몇 점 맞았나와 비슷해.
R² = 0.0 → 0점 (모델이 아무것도 설명 못함)
R² = 0.5 → 50점 (절반 정도 설명)
R² = 1.0 → 100점 (완벽하게 설명)
R² < 0 → 그냥 평균 찍는 것보다 못함 😅
정확히 말하면: R²는 "모델이 데이터의 변동을 얼마나 설명하는가"를 0~1로 표현.
R² = 1 - (모델의 오차) / (그냥 평균 찍었을 때 오차)
예시로 확인:
집 가격 데이터 평균: 300만원
[그냥 평균 찍기] → 모든 집을 300만원으로 예측
[우리 모델] → 면적 보고 예측
R² = 0.85라면?
→ "그냥 평균 찍는 것보다 85% 더 잘 설명한다"
→ "데이터 변동의 85%를 모델이 설명한다"
쉽게 말하면: R²가 1에 가까울수록 좋은 모델!
🔨 따라하기¶
📦 데이터셋 선택지 - 옵션 A: 캘리포니아 집 가격 (sklearn 내장) - 옵션 B: 당뇨병 진행도 예측 (sklearn 내장) - 옵션 C: 직접 만든 간단한 데이터
이 장에서는 캘리포니아 집 가격 데이터를 사용합니다. 어떤 회귀 데이터든 동일한 방법으로 분석할 수 있어요!
Step 1: 환경 준비와 데이터 불러오기¶
목표: sklearn에서 회귀용 데이터셋 불러오기
# === WHAT: 회귀 분석에 필요한 라이브러리와 데이터 불러오기 ===
# --- WHY: 회귀 모델과 평가 도구가 필요해서 ---
import pandas as pd # 데이터프레임
import numpy as np # 수치 계산
import matplotlib.pyplot as plt # 시각화
# sklearn에서 필요한 것들
from sklearn.datasets import fetch_california_housing # 데이터
from sklearn.model_selection import train_test_split # 데이터 분할
from sklearn.linear_model import LinearRegression # 선형 회귀
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score # 평가
# --- 캘리포니아 집 가격 데이터 불러오기 ---
housing = fetch_california_housing()
# 데이터프레임으로 변환
df = pd.DataFrame(housing.data, columns=housing.feature_names)
df['Price'] = housing.target # 타겟(집 가격)은 10만 달러 단위
print("=== 캘리포니아 집 가격 데이터 ===")
print(f"데이터 크기: {df.shape}")
print(f"\n컬럼 설명:")
print("- MedInc: 중위 소득")
print("- HouseAge: 집 연식")
print("- AveRooms: 평균 방 개수")
print("- AveBedrms: 평균 침실 개수")
print("- Population: 인구")
print("- AveOccup: 평균 거주자 수")
print("- Latitude: 위도")
print("- Longitude: 경도")
print("- Price: 집 가격 (10만 달러 단위)")
print()
print(df.head())
실행 결과: ``` === 캘리포니아 집 가격 데이터 === 데이터 크기: (20640, 9)
컬럼 설명: - MedInc: 중위 소득 - HouseAge: 집 연식 - AveRooms: