# Part 6: 머신러닝 모델링과 평가

**⬅️ 이전 시간: [Part 5.6: 머신러닝/딥러닝을 위한 미적분](../05.6_calculus_for_ml/part_5.6_calculus_for_ml.md)**
**➡️ 다음 시간: [Part 7: 딥러닝 기초와 PyTorch](../07_deep_learning/part_7_deep_learning.md)**

---

## 🗺️ 학습 로드맵: 이제 실제 AI 모델을 만들어봅시다!

### 🎯 이번 파트의 목적
이제 선형대수와 미적분의 기초를 다졌으니, **실제 머신러닝 모델을 만들어보겠습니다!** 이전 파트들의 모든 지식이 하나로 합쳐지는 순간입니다.

### 🔗 이전 파트들의 지식이 어떻게 활용되는지
- **Part 5 (AI Core Libraries)**: NumPy, Pandas로 데이터를 다루고 전처리
- **Part 5.5 (Linear Algebra)**: 벡터와 행렬로 데이터를 표현하고 변환
- **Part 5.6 (Calculus)**: 기울기 하강법으로 모델을 최적화
- **이번 파트 (Machine Learning)**: 모든 것을 결합하여 실제 예측 모델 구축

### 🚀 머신러닝의 핵심 구성 요소
- **데이터 시각화**: Matplotlib, Seaborn으로 패턴 발견
- **지도학습**: 정답이 있는 데이터로 패턴 학습
- **모델 평가**: 훈련/테스트 분리로 일반화 성능 측정
- **전처리**: 피처 스케일링으로 모델 성능 향상

### 📈 학습 진행도
```
Part 5: AI Core Libraries ✅
Part 5.5: Linear Algebra ✅
Part 5.6: Calculus ✅
Part 6: Machine Learning 🔄 (현재)
Part 7: Deep Learning ⏳
```

### 🎯 이제 할 수 있는 것들
- **실제 예측 모델 구축**: 집값 예측, 고객 이탈 예측 등
- **데이터 기반 의사결정**: 시각화를 통한 인사이트 도출
- **모델 성능 최적화**: 하이퍼파라미터 튜닝, 앙상블 기법
- **실무 프로젝트**: 전체 머신러닝 파이프라인 구축

---

<br>

> ## 1. 학습 목표 (Learning Objectives)
>
> 이번 파트가 끝나면, 여러분은 다음을 할 수 있게 됩니다.
> 
> - Matplotlib와 Seaborn을 사용하여 데이터의 분포, 관계, 추세를 시각화하고 인사이트를 도출할 수 있습니다.
> - 지도학습, 훈련/테스트 데이터 분할의 개념을 설명할 수 있습니다.
> - Scikit-learn의 `fit()`, `predict()` 인터페이스를 사용하여 머신러닝 모델을 훈련하고, 새로운 데이터에 대한 예측을 만들 수 있습니다.
> - 피처 스케일링(StandardScaler, MinMaxScaler)과 같은 핵심 전처리 기법을 모델 성능 향상을 위해 적용할 수 있습니다.
> - 데이터 불러오기부터 전처리, 훈련, 평가까지 이어지는 머신러닝의 전체 파이프라인을 코드로 구현할 수 있습니다.

<br>

> ## 2. 핵심 요약 (Key Summary)
> 
> 이 파트에서는 데이터에서 패턴을 발견하고 미래를 예측하는 머신러닝의 전 과정을 학습합니다. Matplotlib와 Seaborn을 이용한 데이터 시각화로 숨겨진 인사이트를 찾는 법을 배우고, Scikit-learn 라이브러리를 통해 지도학습의 기본 개념과 모델 훈련/평가 프로세스를 익힙니다. 훈련/테스트 데이터 분리, 피처 스케일링 등 핵심적인 데이터 전처리 기법을 적용하여 모델의 성능을 향상시키는 방법을 실습하며, 머신러닝 프로젝트의 전체 파이프라인을 직접 구축해 봅니다.
> 
> - **핵심 키워드**: `데이터 시각화`, `Matplotlib`, `Seaborn`, `Scikit-learn`, `지도학습(Supervised Learning)`, `훈련/테스트 분리(Train/Test Split)`, `데이터 전처리(Preprocessing)`, `피처 스케일링(Feature Scaling)`, `모델 평가(Evaluation)`, `정확도(Accuracy)`

<br>

> ## 3. 도입: 데이터에서 지혜를 캐내는 기술 (Introduction)
>
> 이전 파트에서 우리는 NumPy와 Pandas로 데이터를 자유자재로 다루는 법을 배웠습니다. 하지만 숫자로만 가득한 표는 우리에게 많은 것을 알려주지 않습니다. 이번 파트에서는 데이터에 '생명'을 불어넣는 두 가지 핵심 기술, **시각화**와 **머신러닝**을 배웁니다.
> 
> - **시각화**는 데이터 속에 숨겨진 패턴과 이야기를 발견하는 '눈'이 되어줄 것입니다.
> - **머신러닝**은 그 패턴을 학습하여 미래를 예측하는 '두뇌' 역할을 합니다.
> 
> Scikit-learn이라는 강력한 도구를 통해, 우리는 이 모든 과정을 직접 체험해볼 것입니다.
> 
> > [!TIP]
> > 본 파트의 모든 예제 코드는 `../../source_code/part_6_machine_learning.py` 파일에서 직접 실행하고 수정해볼 수 있습니다.

---

<br>

> ## 4. 데이터 시각화: 그림으로 데이터와 대화하기
> 
> > **🎯 1-2일차 목표:** Matplotlib와 Seaborn으로 데이터를 시각화하여 인사이트를 발견합니다.
> 
> 데이터를 숫자로만 보는 것은 숲을 보지 못하고 나무만 보는 것과 같습니다. 시각화는 데이터 속에 숨겨진 패턴, 관계, 이상치를 한눈에 파악하게 해주는 강력한 도구입니다.
> 
> - **Matplotlib**: 파이썬 시각화의 근간. 거의 모든 종류의 그래프를 그릴 수 있습니다. (비유: 하얀 도화지)
> - **Seaborn**: Matplotlib을 더 쉽고 예쁘게 사용하도록 만든 고수준 라이브러리. 통계 기능이 특화되어 있습니다. (비유: 밑그림과 색칠 도구가 갖춰진 스케치북)
> 
> #### 4-1. 어떤 그래프를 언제 쓸까?
> - **선 그래프 (Line Plot)**: 시간에 따른 주가 변화처럼, 연속적인 데이터의 **추세**를 볼 때
> - **막대 그래프 (Bar Plot)**: 반별 평균 키처럼, 여러 그룹 간의 값을 **비교**할 때
> - **산점도 (Scatter Plot)**: 공부 시간과 성적처럼, 두 변수 간의 **관계**나 분포를 볼 때
> - **히스토그램 (Histogram)**: 우리 반 학생들의 키 분포처럼, 데이터의 **분포**를 볼 때
> - **히트맵 (Heatmap)**: 여러 변수들 간의 상관관계를 한눈에 **색상**으로 파악할 때
> 
> #### 4-2. Seaborn 실전 예제
> ```python
import matplotlib.pyplot as plt
import seaborn as sns

# Seaborn에 내장된 'tips' 데이터셋 사용
tips = sns.load_dataset("tips")

# 1. 산점도: 총 식사 금액과 팁 사이의 관계
plt.figure(figsize=(8, 6))
sns.scatterplot(x="total_bill", y="tip", data=tips, hue="smoker", size="size")
plt.title("Total Bill vs Tip Amount")
plt.xlabel("Total Bill ($)")
plt.ylabel("Tip ($)")
plt.grid(True)
plt.show()

# 2. 막대 그래프: 요일별 평균 팁
plt.figure(figsize=(8, 6))
sns.barplot(x="day", y="tip", data=tips, errorbar=None) # errorbar=None은 신뢰구간 제거
plt.title("Average Tip by Day of the Week")
plt.show()
```

---

<br>

> ## 4.5. 머신러닝의 종류: 어떤 문제를 풀고 싶은가?
> 
> 본격적으로 모델을 만들기 전에, 머신러닝이 해결할 수 있는 문제의 종류를 이해하는 것은 매우 중요합니다. 머신러닝은 크게 **지도학습, 비지도학습, 강화학습** 세 가지로 나뉩니다.
> 
> | 학습 유형 | 핵심 아이디어 | 대표적인 예시 | 주요 알고리즘 |
> | :--- | :--- | :--- | :--- |
> | **지도학습<br>(Supervised)** | **'정답'이 있는 데이터**로 학습 | 스팸 메일 분류, 집값 예측, 이미지 분류 (개/고양이) | 선형 회귀, 로지스틱 회귀, SVM, 결정 트리, 랜덤 포레스트 |
> | **비지도학습<br>(Unsupervised)** | **'정답'이 없는 데이터**에서 패턴 발견 | 고객 그룹 분석, 토픽 모델링, 이상 탐지 | K-평균 군집, 주성분 분석(PCA) |
> | **강화학습<br>(Reinforcement)** | **'보상'**을 최대화하는 행동을 학습 | 알파고(바둑), 자율주행, 로봇 제어 | Q-러닝, SARSA, DQN |
> 
> ![머신러닝 종류](https://i.imgur.com/8aE5E9U.png)
> 
> 이번 파트에서는 이 중에서 가장 널리 사용되고 산업적으로도 중요한 **지도학습**에 집중하여, '정답'이 주어진 데이터를 통해 미래를 예측하는 모델을 만드는 방법을 깊이 있게 다룰 것입니다.

---

<br>

> ## 5. Scikit-learn으로 첫 머신러닝 모델 만들기
> 
> > **🎯 3-4일차 목표:** Scikit-learn을 사용하여 머신러닝의 기본 프로세스(학습, 예측, 평가)를 이해합니다.
> 
> ### 5-1. 머신러닝의 핵심: 훈련과 시험
> - **지도학습(Supervised Learning)**: **입력(문제)**과 **정답**이 있는 데이터를 사용해, 문제와 정답 사이의 '패턴'을 기계에 학습시키는 방법입니다.
> 
> > [!NOTE] 비유: 머신러닝은 '공부'와 '시험' 과정입니다.
> > - **훈련 데이터 (Training Data)**: 모델이 학습하는 데 사용하는 **'교과서/모의고사'**.
> > - **테스트 데이터 (Test Data)**: 모델의 최종 성능을 평가하기 위해, 학습 과정에서 **전혀 사용하지 않은 새로운 '수능 문제'**.
> >
> > 훈련 데이터로만 반복해서 시험 보면 100점이 나오겠지만, 진짜 실력이라고 할 수 없겠죠? 그래서 우리는 훈련/테스트 데이터를 엄격히 분리하여 모델의 **일반화 성능**(처음 보는 데이터에 대한 예측 능력)을 측정합니다.
> 
> ### 5-2. 핵심 개념: 과적합, 과소적합, 그리고 편향-분산 트레이드오프
> 
> 모델을 훈련시킬 때 가장 흔하게 마주치는 문제는 **과적합(Overfitting)**과 **과소적합(Underfitting)**입니다.
> 
> - **과소적합 (Underfitting)**: 모델이 너무 단순해서 데이터의 내재된 패턴을 제대로 학습하지 못하는 상태입니다. **훈련 데이터에서도 성능이 낮고, 테스트 데이터에서도 성능이 낮은** 특징을 보입니다. (비유: 시험 범위의 절반만 공부한 학생)
> - **과적합 (Overfitting)**: 모델이 훈련 데이터에만 너무 과도하게 맞춰져, 노이즈나 특정 패턴까지 전부 외워버린 상태입니다. **훈련 데이터에서는 성능이 매우 높지만, 새로운 테스트 데이터에서는 성능이 급격히 떨어지는** 특징을 보입니다. (비유: 모의고사 족보만 달달 외워, 새로운 유형의 수능 문제에 대처하지 못하는 학생)
> 
> 이 두 문제는 **모델의 복잡도(Model Complexity)**와 깊은 관련이 있으며, 이를 **편향-분산 트레이드오프(Bias-Variance Tradeoff)** 라고 부릅니다.
> 
> ![Bias-Variance Tradeoff](https://i.imgur.com/2s42p4s.png)
> 
> - **편향 (Bias)**: 모델이 실제 관계와 얼마나 다른지를 나타냅니다. 편향이 높으면 모델이 너무 단순하여 과소적합 경향을 보입니다.
> - **분산 (Variance)**: 데이터의 작은 변화에 모델이 얼마나 민감하게 변하는지를 나타냅니다. 분산이 높으면 모델이 너무 복잡하여 과적합 경향을 보입니다.
> 
> 우리의 목표는 **편향과 분산이 모두 낮은, 즉 전체 오류가 최소가 되는 '최적의 균형점(Optimal Balance)'**을 찾는 것입니다.
> 
> ### 5-3. Scikit-learn 기본 4단계 프로세스
> Scikit-learn은 다음과 같은 통일된 인터페이스를 제공하여 누구나 쉽게 머신러닝 모델을 만들 수 있게 해줍니다.
> 
> 1.  **모델 객체 생성**: `model = ModelName()`
> 2.  **모델 학습**: `model.fit(X_train, y_train)` (훈련 데이터로 공부)
> 3.  **예측**: `predictions = model.predict(X_test)` (테스트 데이터로 시험)
> 4.  **평가**: `score = accuracy_score(y_test, predictions)` (채점)
> 
> ```python
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
import seaborn as sns
import numpy as np

# 데이터 로드 (붓꽃 데이터)
iris = sns.load_dataset("iris")
X, y = iris.drop("species", axis=1), iris["species"]

# 1. 데이터 분리 (훈련 80%, 테스트 20%)
# stratify=y : 훈련/테스트 데이터의 클래스 비율을 원본과 동일하게 유지
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)

# 2. 모델 생성 및 학습
model = DecisionTreeClassifier(random_state=42)
model.fit(X_train, y_train)

# 3. 예측
predictions = model.predict(X_test)

# 4. 평가 (정확도)
accuracy = accuracy_score(y_test, predictions)
print(f"정확도: {accuracy:.4f}")
```

### 5-4. 모델 성능을 높이는 데이터 전처리
모델의 성능은 알고리즘만큼이나 **'데이터의 품질'**에 크게 좌우됩니다. "Garbage In, Garbage Out" (쓰레기를 넣으면 쓰레기가 나온다) 라는 말이 있을 정도입니다.

- **피처 스케일링(Feature Scaling)**: 변수들의 단위를 맞춰줍니다. (예: 키(cm)와 몸무게(kg) -> 0~1 사이 값으로 표준화)
    - **StandardScaler**: 평균 0, 표준편차 1로 변환. (분포가 정규분포에 가까울 때 효과적)
    - **MinMaxScaler**: 최솟값 0, 최댓값 1로 변환. (모든 값을 0과 1 사이로 만들고 싶을 때)

> [!NOTE] 스케일러의 수학적 원리
> 
> - **StandardScaler (표준화)**: 각 특성의 평균(μ)을 0, 표준편차(σ)를 1로 만듭니다.
>   \[ z = \frac{x - \mu}{\sigma} \]
>   이는 데이터의 분포를 정규분포와 유사하게 만들어, 거리 기반 알고리즘(e.g., SVM, 로지스틱 회귀)이나 경사 하강법을 사용하는 모델의 성능을 향상시키는 데 도움을 줍니다.
> 
> - **MinMaxScaler (정규화)**: 각 특성의 모든 값을 0과 1 사이로 조정합니다.
>   \[ x' = \frac{x - \min(x)}{\max(x) - \min(x)} \]
>   이미지 픽셀 값을 0~255에서 0~1 사이로 변환하거나, 신경망 모델의 입력으로 사용할 때 자주 사용됩니다.
> 
> ```python
from sklearn.preprocessing import StandardScaler, MinMaxScaler
import numpy as np

data = np.array([[170, 70], [180, 85], [160, 55]], dtype=float)

scaler_std = StandardScaler()
scaled_std = scaler_std.fit_transform(data)
print("StandardScaler 결과:\n", scaled_std)

scaler_minmax = MinMaxScaler()
scaled_minmax = scaler_minmax.fit_transform(data)
print("\nMinMaxScaler 결과:\n", scaled_minmax)
```

### 5-5. 모델 상세 평가: 정확도를 넘어서

모델의 성능을 단순히 '정확도(Accuracy)' 하나만으로 평가하는 것은 때로는 위험할 수 있습니다. 특히 데이터가 불균형할 때(예: 스팸 메일 1%, 정상 메일 99%)는 더욱 그렇습니다.

#### 혼동 행렬 (Confusion Matrix)
모델의 예측이 얼마나 헷갈렸는지(confused)를 보여주는 표입니다.

- **TN (True Negative)**: 음성(Negative)을 음성으로 올바르게 예측
- **FP (False Positive)**: 음성(Negative)을 양성(Positive)으로 잘못 예측 (Type I Error)
- **FN (False Negative)**: 양성(Positive)을 음성(Negative)으로 잘못 예측 (Type II Error)
- **TP (True Positive)**: 양성(Positive)을 양성으로 올바르게 예측

![Confusion Matrix](https://i.imgur.com/A4EGF24.png)

#### 정밀도, 재현율, F1-Score
- **정밀도 (Precision)** = `TP / (TP + FP)`
  - 모델이 "양성"이라고 예측한 것들 중, 실제로 양성이었던 것의 비율입니다.
  - **"스팸이라고 예측한 메일 중, 진짜 스팸은 얼마나 되는가?"**
  - FP(정상 메일을 스팸으로 처리)를 낮추는 것이 중요할 때 사용합니다. (예: 유튜브 키즈 콘텐츠 필터링)
- **재현율 (Recall)** = `TP / (TP + FN)`
  - 실제 양성인 것들 중, 모델이 양성으로 예측한 것의 비율입니다.
  - **"실제 암 환자 중, 모델이 암이라고 진단한 비율은 얼마인가?"**
  - FN(암 환자를 정상으로 진단)을 낮추는 것이 중요할 때 사용합니다. (예: 의료 진단, 금융 사기 탐지)
- **F1-Score** = `2 * (Precision * Recall) / (Precision + Recall)`
  - 정밀도와 재현율의 조화 평균입니다. 두 지표가 모두 중요할 때 사용하며, 데이터가 불균형할 때 정확도보다 훨씬 신뢰할 수 있는 지표입니다.

```python
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score

# ... (이전 코드에서 predictions, y_test가 생성되었다고 가정) ...

# 혼동 행렬
conf_matrix = confusion_matrix(y_test, predictions)
print("Confusion Matrix:\n", conf_matrix)

# 정밀도, 재현율, F1-점수
precision = precision_score(y_test, predictions, average='macro') # 다중 클래스일 경우 average 지정
recall = recall_score(y_test, predictions, average='macro')
f1 = f1_score(y_test, predictions, average='macro')

print(f"Precision: {precision:.4f}")
print(f"Recall: {recall:.4f}")
print(f"F1 Score: {f1:.4f}")
```

### 5-6. 심화: 어떤 모델을 언제 사용해야 할까? (Model Selection Guide)

Scikit-learn에는 수많은 머신러닝 모델이 존재합니다. 문제의 종류, 데이터의 특성, 그리고 우리가 추구하는 목표(성능, 해석 가능성, 속도 등)에 따라 최적의 모델은 달라집니다. 여기서는 가장 대표적인 **분류(Classification)** 모델 몇 가지를 비교하고, 언제 어떤 모델을 선택하는 것이 좋은지에 대한 가이드라인을 제시합니다.

| 모델 | 핵심 아이디어 | 장점 | 단점 | 언제 사용하면 좋을까? |
| :--- | :--- | :--- | :--- | :--- |
| **로지스틱 회귀<br>(Logistic Regression)** | 데이터가 특정 클래스에 속할 확률을 선형 결정 경계로 예측 | 빠르고, 간단하며, **해석이 용이함**. 모델의 계수가 각 특성의 중요도를 나타냄. | 복잡한 비선형 관계를 학습하기 어려움. | **모델의 해석**이 중요할 때 (e.g., 금융, 의료), 베이스라인 모델로 사용하기 좋음. |
| **결정 트리<br>(Decision Tree)** | 데이터를 '예/아니오' 질문(규칙)의 연속으로 나누어 예측 | **결과를 이해하기 쉬움 (White Box)**. 시각화가 가능함. 스케일링이 필요 없음. | **과적합(Overfitting) 위험이 높음**. 데이터의 작은 변화에도 모델이 크게 변동될 수 있음. | 규칙 기반으로 데이터를 설명하고 싶을 때. (e.g., 고객 이탈 원인 분석) |
| **랜덤 포레스트<br>(Random Forest)** | 여러 개의 작은 결정 트리들을 만들어, 그 결과를 **투표(Voting)**하여 종합. (앙상블 기법) | **성능이 매우 우수함**. 과적합에 강하고 안정적임. | 결정 트리보다 **해석이 어려움 (Black Box)**. 훈련 속도가 느리고 메모리를 더 많이 사용. | **높은 예측 성능**이 가장 중요할 때. 대부분의 분류 문제에서 좋은 성능을 보임. |
| **서포트 벡터 머신<br>(SVM)** | 클래스 간의 **마진(Margin)을 최대화**하는 결정 경계를 찾음. | 고차원 데이터에서 잘 작동하며, 과적합에 강함. | 데이터가 많을 때 훈련 속도가 매우 느림. 파라미터 튜닝에 민감함. | 특성(Feature)이 매우 많은 복잡한 데이터셋 (e.g., 이미지, 바이오인포매틱스)에 효과적. |

> [!NOTE] 핵심 질문: 해석 가능성(Interpretability) vs. 성능(Performance)
> - **해석이 중요하다면?** -> Logistic Regression, Decision Tree
> - **성능이 중요하다면?** -> Random Forest, Gradient Boosting (더 발전된 앙상블), SVM
>
> 실무에서는 먼저 Logistic Regression이나 Decision Tree 같은 간단한 모델로 베이스라인을 설정하고, 점차 Random Forest나 Gradient Boosting과 같은 복잡한 모델로 성능을 높여가는 방식을 많이 사용합니다.

이 가이드는 시작점일 뿐이며, 최고의 모델을 찾는 유일한 방법은 **직접 여러 모델을 실험해보고, 교차 검증(Cross-validation)을 통해 성능을 객관적으로 평가하는 것**입니다.

### 5-7. 핵심 개념: 교차 검증 (Cross-Validation)

우리가 데이터를 훈련/테스트 세트로 한 번 나누는 것은 마치 모의고사를 딱 한 번만 보고 수능 점수를 예측하는 것과 같습니다. 이 분할이 어떻게 되었는지에 따라 성능이 우연히 좋거나 나쁘게 나올 수 있습니다.

**교차 검증(Cross-Validation)**은 이 문제를 해결하기 위해 데이터를 여러 번 다른 방식으로 나누어 학습과 평가를 반복하는 방법입니다. 가장 널리 쓰이는 방법은 **K-겹 교차 검증(K-Fold Cross-Validation)**입니다.

1. 전체 데이터를 K개의 '겹(Fold)'으로 나눕니다.
2. 첫 번째 겹을 테스트 데이터로 사용하고, 나머지 K-1개 겹을 훈련 데이터로 사용하여 모델을 학습하고 평가합니다.
3. 두 번째 겹을 테스트 데이터로 사용하고, 나머지를 훈련 데이터로 사용하여 다시 학습하고 평가합니다.
4. 이 과정을 K번 반복하여, K개의 성능 점수를 얻습니다.
5. 최종적으로 이 K개의 점수를 평균내어 모델의 일반화된 성능을 추정합니다.

![K-Fold Cross Validation](https://i.imgur.com/0K3jTf7.png)

> [!NOTE] 장점:
> - 데이터를 더 효율적으로 사용하며, 모델의 성능을 훨씬 더 안정적이고 신뢰성 있게 평가할 수 있습니다.
> - 특정 데이터 분할에 따른 성능 변동의 위험을 줄여줍니다.

```python
from sklearn.model_selection import cross_val_score

# 모델 생성
model = DecisionTreeClassifier(random_state=42)

# 5-겹 교차 검증 수행
# cv=5 : 5개의 폴드로 나눔
# scoring='accuracy' : 평가 지표로 정확도 사용
scores = cross_val_score(model, X_train, y_train, cv=5, scoring='accuracy')

print(f"교차 검증 점수: {scores}")
print(f"평균 정확도: {scores.mean():.4f} (+/- {scores.std() * 2:.4f})")
```

### 5-8. 실제 기업 적용 사례 (Real-world Enterprise Use Cases)

우리가 배운 머신러닝 기술은 단순히 학문적인 개념에 머무르지 않고, 오늘날 수많은 글로벌 기업들의 핵심 서비스를 구동하는 엔진이 되고 있습니다. 몇 가지 대표적인 사례를 통해 머신러닝이 실제로 어떻게 가치를 창출하는지 살펴보겠습니다.

| 기업 | 적용 분야 | 사용 기술 및 모델 (추정) | 비즈니스 가치 |
| :--- | :--- | :--- | :--- |
| **Netflix** | **영화/드라마 추천 시스템** | 협업 필터링, 콘텐츠 기반 필터링, 랭킹 알고리즘 (e.g., Logistic Regression, Gradient Boosting) | 개인화된 콘텐츠 추천을 통해 **고객 이탈률을 낮추고**, 사용자 만족도를 극대화. (매년 1조 원 이상의 가치 창출) |
| **Google** | **Gmail 스팸 필터** | 지도 학습 분류기 (e.g., Naive Bayes, Logistic Regression), 딥러닝(RNN, Transformer) | 매일 수십억 개의 스팸 메일을 99.9% 이상의 정확도로 차단하여, **사용자 경험을 보호**하고 보안 위협을 감소시킴. |
| **Google** | **검색 결과 랭킹 (RankBrain)** | 학습-투-랭크(Learning to Rank) 알고리즘 | 이전에는 없었던 새로운 검색어(전체 검색의 15%)에 대해 **가장 관련성 높은 결과를 추론**하여 제시. 검색 품질 향상. |
| **Meta (Facebook)** | **뉴스피드 랭킹** | 랭킹 알고리즘, 대규모 추천 시스템 | 수천 개의 잠재적 게시물 중 사용자에게 가장 흥미로울 만한 콘텐츠를 예측하여 보여줌으로써, **플랫폼 체류 시간을 늘리고** 광고 효율을 높임. |
| **Amazon** | **상품 추천 (Customers who bought this item also bought...)** | 협업 필터링 (Item-to-Item), 개인화 랭킹 | 사용자의 구매 패턴을 분석하여 관련 상품을 추천함으로써, **객단가(Average Order Value)를 높이고** 새로운 상품을 발견할 기회를 제공. |

> [!NOTE] 시사점: 문제 정의의 중요성
> 위 사례들의 공통점은 기술 자체가 목적이 아니라, '고객 이탈 방지', '사용자 경험 보호', '관련성 높은 정보 제공'과 같은 **명확한 비즈니스 문제를 해결하기 위해 머신러닝을 '도구'로 사용했다는 점**입니다. 성공적인 머신러닝 프로젝트를 위해서는 "어떤 모델을 쓸까?" 보다 "**어떤 문제를 풀고 싶은가?**"를 먼저 정의하는 것이 중요합니다.

---

## 7. 심화 토론: 무엇이 잘못될 수 있을까?

Scikit-learn을 사용하면 몇 줄의 코드로 쉽게 모델을 만들 수 있지만, 그 과정에는 수많은 함정이 존재합니다. "동작하는" 코드를 넘어 "올바른" 코드를 작성하기 위해 다음 주제들에 대해 함께 토론해보세요.

1.  **전처리 순서가 초래한 데이터 누수(Data Leakage)**
    -   **상황**: 한 동료가 효율성을 위해 전체 데이터셋 `X`에 대해 `StandardScaler`를 먼저 적용(`fit_transform`)한 후, 그 결과를 `train_test_split`으로 나누어 모델을 학습시켰습니다. 코드는 오류 없이 잘 동작했고, 테스트 정확도도 꽤 높게 나왔습니다.
    -   **토론**:
        -   이 접근 방식의 무엇이 치명적인 실수일까요? 테스트셋의 정보가 훈련 과정에 어떻게 "누수"되었을까요? (힌트: `fit` 메소드는 데이터의 평균과 표준편차를 계산합니다.)
        -   피처 스케일링과 같은 전처리 단계를 올바르게 적용하는 파이프라인은 어떤 순서로 구성되어야 할까요? 왜 그 순서가 중요한가요?

2.  **"완벽한" 테스트 점수에 대한 의심**
    -   **상황**: 타이타닉 생존자 예측 문제를 해결하기 위해 여러 모델과 특성을 조합해본 결과, 마침내 제공된 테스트셋에 대해 100%의 정확도를 달성했습니다.
    -   **토론**:
        -   이 결과를 기뻐해야 할까요, 아니면 의심해야 할까요? "완벽한" 점수가 나올 수 있는 잠재적인 원인들은 무엇일까요? (예: 타겟 변수가 특성에 포함됨, 테스트셋이 너무 작거나 대표성이 없음, 특정 테스트셋에 대한 과적합 등)
        -   실제 서비스를 만든다고 가정할 때, 왜 최종 성능 검증을 위해 단 한 번만 사용하는 별도의 "검증(validation) 데이터셋"을 따로 떼어놓는 것이 중요한지 토론해보세요.

3.  **특성 중요도(Feature Importance)의 섣부른 해석**
    -   **상황**: 고객 이탈 예측을 위해 만든 랜덤 포레스트 모델이 '월 청구요금'을 가장 중요한 특성으로 지목했습니다. 이 결과를 보고, 마케팅팀은 모든 고객의 요금을 인하하는 캠페인을 기획하려 합니다.
    -   **토론**:
        -   이러한 의사 결정이 왜 섣부른 판단일 수 있을까요? 랜덤 포레스트는 특성 중요도를 어떤 방식으로 계산하나요?
        -   높은 특성 중요도가 '인과 관계'를 의미할까요, 아니면 단순한 '상관 관계'일 가능성이 높을까요? 이처럼 중요한 비즈니스 결정을 내리기 전에, 어떤 추가적인 분석이나 실험을 수행해야 할까요?

## 8. 되짚어보기 (Summary)

이번 주 우리는 데이터에서 패턴을 찾아 미래를 예측하는 머신러닝의 세계를 여행했습니다.

- **시각화는 눈**: Matplotlib와 Seaborn으로 데이터 속에 숨겨진 이야기를 보는 법을 배웠습니다.
- **머신러닝은 뇌**: Scikit-learn을 사용해 '훈련'과 '시험'이라는 과정을 거쳐 예측 모델을 만드는 법을 익혔습니다.
- **데이터는 생명**: "Garbage In, Garbage Out." 좋은 예측을 위해서는 결측치 처리, 피처 스케일링과 같은 데이터 전처리가 필수임을 이해했습니다.

이제 여러분은 데이터를 분석하고 예측 모델을 만들 수 있는 기본적인 역량을 갖추었습니다.

---
## 9. 트러블슈팅 (Troubleshooting)

- **그래프에 한글이 깨져서 `□□□` 형태로 나오나요?**
  - Matplotlib가 기본적으로 한글 폰트를 지원하지 않기 때문입니다. 아래 코드를 실행하여 시스템에 맞는 한글 폰트를 설정해주어야 합니다.

    ```python
    import matplotlib.pyplot as plt
    # For Windows
    # plt.rcParams['font.family'] = 'Malgun Gothic'
    # For macOS
    # plt.rcParams['font.family'] = 'AppleGothic'
    ```

- **`fit_transform()`은 훈련 데이터에만 사용하고, `transform()`은 테스트 데이터에 사용하라는 말이 무슨 뜻인가요?**
  - `fit()`은 데이터로부터 스케일링에 필요한 정보(e.g., 평균, 표준편차, 최소/최대값)를 '학습'하는 과정입니다. `transform()`은 학습된 정보를 바탕으로 데이터를 변환합니다. `fit_transform()`은 이 두 과정을 한 번에 수행합니다. 테스트 데이터는 '미래의 데이터'를 의미하므로, 훈련 데이터로 `fit()`한 스케일러를 사용하여 `transform()`만 적용해야 합니다.

- **모델의 성능이 너무 낮게 나오나요?**
  - 여러 가능성이 있습니다.
    - **데이터 전처리**: 결측치를 적절히 처리했나요? 범주형 변수(e.g., 'sex')를 숫자로 변환했나요? 피처 스케일링이 필요한 모델인데 적용했나요?
    - **특성 선택**: 모델에 너무 적은 특성을 사용했거나, 반대로 예측에 도움이 되지 않는 불필요한 특성을 너무 많이 사용했을 수 있습니다.
    - **모델 선택**: 현재 문제에 적합하지 않은 모델을 사용했을 수 있습니다. 'Model Selection Guide'를 참고하여 다른 모델을 시도해보세요.
    - **과적합/과소적합**: 훈련 데이터의 점수는 높은데 테스트 데이터의 점수가 현저히 낮다면 과적합(Overfitting)을, 둘 다 낮다면 과소적합(Underfitting)을 의심해볼 수 있습니다.

- **`ValueError: Input contains NaN, infinity or a value too large for dtype('float64').` 오류가 발생했나요?**
  - 모델의 입력 데이터(`X_train`)에 결측치(NaN), 무한대(infinity) 값이 포함되어 있다는 의미입니다. 모델을 학습시키기 전, `X_train.isnull().sum()` 과 같은 코드로 결측치를 확인하고, `fillna()` 등을 사용하여 적절히 처리해야 합니다.

더 자세한 문제 해결 가이드나 다른 동료들이 겪은 문제에 대한 해결책이 궁금하다면, 아래 문서를 참고해주세요.

- **➡️ [Geumdo-Docs: TROUBLESHOOTING.md](../../../TROUBLESHOOTING.md)**

---

## 10. 더 깊이 알아보기 (Further Reading)

### 실전 코드 & 튜토리얼
- [Scikit-learn 공식 예제 갤러리](https://scikit-learn.org/stable/auto_examples/index.html): 다양한 모델과 데이터셋에 대한 예제 코드의 보고
- [Seaborn 공식 튜토리얼](https://seaborn.pydata.org/tutorial.html): 더 아름답고 전문적인 시각화를 위한 가이드
- [Kaggle](https://www.kaggle.com/): 전 세계 데이터 과학자들이 모여 경쟁하는 플랫폼. 'Titanic'과 같은 다양한 입문용 프로젝트를 체험할 수 있습니다.

### 이론 및 개념 심화
- **[An Introduction to Statistical Learning (ISLR)](https://www.statlearning.com/)**: 머신러닝의 바이블로 불리는 명저. 통계적 이론 배경을 탄탄히 다지고 싶다면 필독을 권합니다. (PDF 무료 제공)
- **[StatQuest 유튜브 채널](https://www.youtube.com/c/statquest)**: 결정 트리, 로지스틱 회귀 등 머신러닝의 핵심 개념들을 가장 직관적이고 명쾌하게 설명해주는 채널입니다.
- **[Scikit-learn: 모델 평가 지표 가이드](https://scikit-learn.org/stable/modules/model_evaluation.html)**: 본문에서 다룬 정확도 외에 정밀도, 재현율, F1-score 등 다양한 평가 지표에 대한 상세한 설명과 사용법을 제공합니다.
- **[Seeing-Theory](https://seeing-theory.brown.edu/index.html)**: 확률 및 통계의 핵심 개념들을 인터랙티브 시각화 자료를 통해 체험하며 배울 수 있는 사이트입니다.

---

## 🚀 캡스톤 미니 프로젝트: 모델 성능 비교 및 파이프라인 구축

이번 장에서는 머신러닝의 전체 흐름을 배웠습니다. 하지만 실전 프로젝트에서는 단 하나의 모델만 만들어보는 경우는 거의 없습니다. 어떤 모델이 이 문제에 가장 적합한지, 그리고 데이터 전처리가 성능에 어떤 영향을 미치는지 체계적으로 '실험'하고 '비교'하는 과정이 필수적입니다.

이번 미니 프로젝트의 목표는 Scikit-learn의 `Pipeline`을 사용하여 데이터 전처리(스케일링)와 모델 훈련을 하나의 파이프라인으로 묶고, 여러 다른 모델의 성능을 체계적으로 비교하여 최적의 모델을 찾는 과정을 경험하는 것입니다.

### 프로젝트 목표

Scikit-learn의 내장 데이터셋인 붓꽃(Iris) 데이터를 사용하여, 다음 세 가지 모델의 성능을 '전처리 적용 전/후'로 나누어 비교하고, 그 결과를 보고서로 작성합니다.
1.  Logistic Regression
2.  Decision Tree Classifier
3.  Random Forest Classifier

**최종 분석 리포트 (예시):**
```
*** Model Performance Comparison Report ***

[Without Scaling]
- LogisticRegression Accuracy: 0.9333
- DecisionTreeClassifier Accuracy: 1.0000
- RandomForestClassifier Accuracy: 1.0000

[With StandardScaler]
- LogisticRegression Accuracy: 1.0000
- DecisionTreeClassifier Accuracy: 1.0000
- RandomForestClassifier Accuracy: 1.0000

[Analysis]
- 스케일링을 적용했을 때 Logistic Regression의 성능이 향상되었습니다.
- 트리 기반 모델인 Decision Tree와 Random Forest는 스케일링의 영향을 받지 않았습니다.
- ...
```

### 단계별 구현 가이드

**1. 데이터 준비**
- `sklearn.datasets`에서 `load_iris` 함수를 사용해 데이터를 불러오세요.
- `train_test_split`을 사용하여 데이터를 훈련셋과 테스트셋으로 분리합니다.

**2. 모델 비교 실험 (스케일링 미적용)**
- 비교할 모델들을 리스트에 담으세요: `[LogisticRegression(), DecisionTreeClassifier(), RandomForestClassifier()]`
- `for` 루프를 사용해 각 모델을 순회하며 다음을 반복합니다.
  - 모델을 훈련 데이터로 학습 (`fit`)
  - 테스트 데이터로 예측 (`predict`)
  - 정확도(`accuracy_score`)를 계산하고 결과를 저장

**3. Scikit-learn `Pipeline`으로 전처리 및 모델링 자동화**
- 데이터 전처리와 모델 학습을 하나의 객체로 묶어주는 `Pipeline`을 사용해 봅시다. 이는 데이터 누수(Data Leakage)를 방지하는 매우 중요한 실무 기법입니다.
- `from sklearn.pipeline import Pipeline`
- `from sklearn.preprocessing import StandardScaler`
- 다시 모델 리스트를 순회하며, 각 모델에 대해 `StandardScaler`와 모델을 포함하는 파이프라인을 생성합니다.
  - `pipe = Pipeline([('scaler', StandardScaler()), ('classifier', model)])`
- 전체 파이프라인을 훈련 데이터로 학습시키고(`pipe.fit`), 테스트 데이터로 정확도를 평가합니다.

**4. 결과 보고 및 분석**
- 위 두 실험(스케일링 전/후)의 결과를 보기 좋게 출력하세요.
- 결과에 대한 분석을 1~2줄로 덧붙여 보세요.
  - 왜 Logistic Regression 모델의 성능은 스케일링 후 변했는데, 트리 기반 모델들은 변하지 않았을까요? (힌트: 각 모델이 데이터를 어떻게 바라보는지 생각해보세요. 거리 기반 vs 규칙 기반)

**전체 코드 구조:**
```python
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from sklearn.pipeline import Pipeline

# 1. 데이터 준비
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 2. 비교할 모델 리스트
models = [
    LogisticRegression(max_iter=1000),
    DecisionTreeClassifier(random_state=42),
    RandomForestClassifier(random_state=42)
]

# 3. 실험: 스케일링 전/후 성능 비교
results_no_scaling = {}
results_with_scaling = {}

print("--- Starting Model Evaluation ---")

for model in models:
    model_name = model.__class__.__name__
    
    # 스케일링 없이 학습 및 평가
    model.fit(X_train, y_train)
    pred_no_scaling = model.predict(X_test)
    results_no_scaling[model_name] = accuracy_score(y_test, pred_no_scaling)

    # 파이프라인으로 스케일링 적용 후 학습 및 평가
    pipe = Pipeline([
        ('scaler', StandardScaler()),
        ('classifier', model)
    ])
    pipe.fit(X_train, y_train)
    pred_with_scaling = pipe.predict(X_test)
    results_with_scaling[model_name] = accuracy_score(y_test, pred_with_scaling)

# 4. 결과 출력
print("\n*** Model Performance Comparison Report ***\n")
print("[Without Scaling]")
for model_name, acc in results_no_scaling.items():
    print(f"- {model_name} Accuracy: {acc:.4f}")

print("\n[With StandardScaler]")
for model_name, acc in results_with_scaling.items():
    print(f"- {model_name} Accuracy: {acc:.4f}")

print("\n[Analysis]")
print("로지스틱 회귀와 같은 거리 기반 알고리즘은 피처 스케일링에 영향을 받지만,")
print("결정 트리 기반 알고리즘은 각 피처를 독립적으로 보기 때문에 스케일링의 영향을 거의 받지 않습니다.")
print("---------------------------------------")
```
이러한 체계적인 실험 과정을 통해, 여러분은 단순히 하나의 모델을 만드는 것을 넘어, 주어진 문제와 데이터에 가장 적합한 해결책을 '찾아내는' 데이터 과학자의 역량을 기르게 될 것입니다.

---

## ✅ Part 6 완료 체크리스트

### 🎯 달성 목표 확인
다음 항목들을 모두 완료했다면 머신러닝의 핵심을 이해한 것입니다!

#### 📊 데이터 시각화 능력
- [ ] Matplotlib와 Seaborn으로 다양한 그래프 생성
- [ ] 데이터의 분포, 관계, 추세를 시각화하여 인사이트 도출
- [ ] 적절한 그래프 유형 선택 (산점도, 히스토그램, 히트맵 등)
- [ ] 시각화를 통한 데이터 품질 문제 발견

#### 🤖 머신러닝 모델링 능력
- [ ] 지도학습의 개념과 훈련/테스트 분할 이해
- [ ] Scikit-learn의 fit(), predict() 인터페이스 활용
- [ ] 다양한 분류 모델 (로지스틱 회귀, 결정 트리, 랜덤 포레스트) 구현
- [ ] 모델 성능 평가 지표 (정확도, 정밀도, 재현율) 이해

#### 🔧 데이터 전처리 능력
- [ ] 피처 스케일링 (StandardScaler, MinMaxScaler) 적용
- [ ] 결측치 처리 및 범주형 변수 인코딩
- [ ] 데이터 누수 방지를 위한 전처리 순서 이해
- [ ] Pipeline을 활용한 전처리 자동화

#### 📈 실무 프로젝트 능력
- [ ] 전체 머신러닝 파이프라인 구축
- [ ] 여러 모델의 성능 비교 및 분석
- [ ] 과적합/과소적합 문제 진단 및 해결
- [ ] 실제 비즈니스 문제에 머신러닝 적용

### 🚀 다음 단계 준비 완료
- [ ] 딥러닝 학습을 위한 기초 준비
- [ ] 신경망 구조와 역전파 이해
- [ ] PyTorch 프레임워크 학습 동기 부여

## 🎯 이제 할 수 있는 것들

### 🚀 즉시 활용 가능한 기술
- **실제 예측 모델 구축**: 집값 예측, 고객 이탈 예측, 스팸 메일 분류
- **데이터 기반 의사결정**: 시각화를 통한 인사이트 도출 및 비즈니스 분석
- **모델 성능 최적화**: 하이퍼파라미터 튜닝, 앙상블 기법 적용
- **실무 머신러닝 파이프라인**: 데이터 전처리부터 모델 배포까지 전체 과정

### 💼 포트폴리오 프로젝트 아이디어
- **부동산 가격 예측 시스템**: 다양한 특성을 활용한 집값 예측 모델
- **고객 이탈 예측 대시보드**: 시각화와 머신러닝을 결합한 분석 도구
- **신용카드 사기 탐지 시스템**: 이상 탐지 알고리즘 구현
- **추천 시스템**: 협업 필터링과 콘텐츠 기반 필터링 결합

### 🔬 실무 적용 예시
- **금융**: 신용 평가, 리스크 관리, 포트폴리오 최적화
- **의료**: 질병 진단, 약물 효과 예측, 환자 결과 예측
- **마케팅**: 고객 세분화, 캠페인 효과 예측, 가격 최적화
- **제조업**: 품질 관리, 예측 정비, 공정 최적화

### 📋 캡스톤 프로젝트 완료도
- [ ] 모델 성능 비교 실험 수행
- [ ] Pipeline을 활용한 전처리 자동화
- [ ] 결과 분석 및 보고서 작성
- [ ] 실무 적용 가능한 인사이트 도출

> **💡 체크리스트 완료 후**: 
> 80% 이상 완료했다면 다음 파트(Part 7: 딥러닝)로 진행하세요!
> 미완료 항목이 있다면 해당 섹션을 다시 학습하고 실습해보세요.

---

**⬅️ 이전 시간: [Part 5.6: 머신러닝/딥러닝을 위한 미적분](../05.6_calculus_for_ml/part_5.6_calculus_for_ml.md)**
**➡️ 다음 시간: [Part 7: 딥러닝 기초와 PyTorch](../07_deep_learning/part_7_deep_learning.md)**
