Guider/AI/AiDevGuide0004
AI#04

AiDevGuide0004

머신러닝 완전 정복

AI DEV GUIDE SERIES — Step 04

🤖 머신러닝 완전 정복 A-Z

Scikit-learn · 분류 · 회귀 · 클러스터링 · 모델 평가 · 파이프라인
비전공자도 현업에서 ML 모델을 직접 만들고 배포하는 완전 마스터

📚 대상: 데이터 분석 완료자⏱ 학습 기간: 3~4주📊 난이도: ★★★☆☆

🗺️ AI Dev Guide 시리즈 전체 흐름

가이드 주제 상태
Guide0001 AI 개념 완전 정복 ✅ 완료
Guide0002 Python 기초 완전 정복 ✅ 완료
Guide0003 데이터 분석 (NumPy·Pandas·Matplotlib) ✅ 완료
Guide0004 🔥 머신러닝 완전 정복 (현재) 📖 학습 중
Guide0005 딥러닝 (TensorFlow·PyTorch) ⏳ 예정
Guide0006 생성형 AI (OpenAI API·LangChain·RAG) ⏳ 예정
Guide0007 실전 프로젝트 (HuggingFace·배포) ⏳ 예정

📋 전체 학습 목차

챕터 주제 핵심 내용 난이도
01 머신러닝 개요 & Scikit-learn ML 워크플로, API 패턴, 설치 ★☆☆☆☆
02 분류 알고리즘 완전 정복 로지스틱 회귀, KNN, SVM, 결정 트리 ★★★☆☆
03 앙상블 — Random Forest & XGBoost 배깅, 부스팅, 특징 중요도 ★★★★☆
04 회귀 알고리즘 완전 정복 선형·릿지·라쏘·ElasticNet 회귀 ★★★☆☆
05 클러스터링 (비지도학습) K-Means, DBSCAN, 계층적 군집화 ★★★☆☆
06 모델 평가 완전 정복 Accuracy, F1, ROC-AUC, MSE, Cross-Val ★★★★☆
07 하이퍼파라미터 튜닝 GridSearch, RandomSearch, Optuna ★★★★☆
08 Pipeline & 전처리 자동화 ColumnTransformer, Pipeline, joblib ★★★★☆
09 실전 프로젝트 — 타이타닉 End-to-End EDA→전처리→모델→평가→제출 ★★★★☆
10 현업 면접 Q&A TOP 10 면접 빈출 질문과 모범 답변 ★★★★★

🌐 Chapter 01. 머신러닝이란? Scikit-learn 완전 입문

ML 워크플로, Scikit-learn API 패턴 — AI 모델의 시작

💡 머신러닝이란?

머신러닝(ML)은 데이터에서 패턴을 학습해 예측·분류·클러스터링을 자동으로 수행하는 기술입니다. 프로그래머가 규칙을 직접 코딩하는 대신, 알고리즘이 데이터로부터 스스로 규칙을 발견합니다. 예: 수만 건의 이메일 데이터를 학습시키면 스팸을 자동으로 구별하는 모델이 만들어집니다.

학습 유형 특징 필요 조건 주요 알고리즘 활용 예시
지도학습 정답 레이블로 학습 레이블 필수 분류, 회귀 스팸 분류, 가격 예측
비지도학습 패턴 자체 발견 레이블 불필요 클러스터링, 차원축소 고객 세분화, 이상 탐지
강화학습 보상으로 정책 학습 환경 필요 Q-Learning, PPO 게임 AI, 로봇 제어

⚙️ Scikit-learn의 5가지 통일 API 패턴

Scikit-learn의 위대함은 모든 알고리즘이 동일한 API 패턴을 사용한다는 것입니다. 한 번 배우면 수십 개 알고리즘을 같은 방식으로 쓸 수 있습니다.

# ===== Scikit-learn 5가지 핵심 API =====
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris

# 1. 데이터 준비
iris = load_iris()
X, y = iris.data, iris.target

# 2. 학습/테스트 분리 (항상 먼저!)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# 3. 전처리 — 스케일링
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)  # fit+transform
X_test = scaler.transform(X_test)         # transform만 (fit 금지!)

# 4. 모델 생성 → fit (학습)
model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train)  # 학습!

# 5. 예측 → 평가
y_pred = model.predict(X_test)
y_proba = model.predict_proba(X_test)  # 확률값
print(f"정확도: {accuracy_score(y_test, y_pred):.4f}")

# ===== 머신러닝 전체 워크플로 요약 =====
# 데이터 수집 → EDA → 전처리 → 모델 선택 → 학습 → 평가 → 튜닝 → 배포

🎯 Chapter 02. 분류 알고리즘 완전 정복

로지스틱 회귀 · KNN · SVM · 결정 트리 — 원리부터 코드까지

📊 분류 알고리즘 한눈에 비교

알고리즘 원리 장점 단점 적합 상황
로지스틱 회귀 시그모이드 함수로 확률 출력 빠름, 해석 용이 비선형 불가 이진 분류, 기준선 모델
KNN 가까운 K개 이웃 다수결 직관적, 비파라미터 대용량 느림 소규모, 추천
SVM 최대 마진 초평면 고차원 강건 대용량 느림, 튜닝 텍스트, 이미지 소규모
결정 트리 정보이득 기반 분기 해석 쉬움, 빠름 과적합 심함 해석 필요한 업무
나이브 베이즈 베이즈 정리 매우 빠름, 텍스트 독립 가정 스팸, 감성 분류
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import classification_report
import numpy as np

# 샘플 분류 데이터 생성
X, y = make_classification(n_samples=1000, n_features=20, n_informative=10,
                           n_redundant=5, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)

# 여러 분류기 한번에 비교 (Scikit-learn의 통일 API 덕분!)
classifiers = {
    "로지스틱 회귀": LogisticRegression(max_iter=1000),
    "KNN(k=5)":     KNeighborsClassifier(n_neighbors=5),
    "SVM(RBF)":     SVC(kernel="rbf", C=1.0, probability=True),
    "결정 트리":    DecisionTreeClassifier(max_depth=5, random_state=42),
}

for name, clf in classifiers.items():
    clf.fit(X_train_s, y_train)
    acc = clf.score(X_test_s, y_test)
    print(f"{name:15s}: 정확도 = {acc:.4f}")

# ===== 결정 트리 — 시각화 (해석 가능 AI) =====
from sklearn.tree import export_text, plot_tree
import matplotlib.pyplot as plt

dt = DecisionTreeClassifier(max_depth=3, random_state=42)
dt.fit(X_train_s, y_train)

# 텍스트로 트리 출력
print(export_text(dt, max_depth=2))

# 시각화
plt.figure(figsize=(14, 6))
plot_tree(dt, max_depth=2, filled=True, feature_names=[f"f{i}" for i in range(20)])
plt.title("결정 트리 시각화")
plt.show()

# ===== 상세 분류 리포트 =====
best_model = SVC(kernel="rbf", C=1.0)
best_model.fit(X_train_s, y_train)
y_pred = best_model.predict(X_test_s)
print(classification_report(y_test, y_pred, target_names=["부정", "긍정"]))
# Precision, Recall, F1-Score, Support 출력

🌲 Chapter 03. 앙상블 — Random Forest & XGBoost 완전 정복

배깅, 부스팅, 스태킹 — 현업 1등 알고리즘의 원리와 실전

💡 앙상블이란? — 여러 모델의 집단 지성

앙상블(Ensemble)은 여러 약한 모델을 결합해 강한 모델을 만드는 기법입니다. 100명의 전문가 의견을 합치면 한 명의 천재보다 낫다는 원리입니다. Kaggle 상위 솔루션 90%가 앙상블을 사용합니다.

🎒 배깅 (Bagging)

데이터를 중복 허용해 샘플링
독립 모델 병렬 학습
Random Forest
분산 감소

⬆️ 부스팅 (Boosting)

이전 모델 오류에 집중
순차적 학습
XGBoost, LightGBM
편향 감소

📚 스태킹 (Stacking)

1차 모델 예측 → 메타 모델
계층적 학습
Kaggle 고득점
분산+편향 감소

from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier, VotingClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import accuracy_score
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

X, y = make_classification(n_samples=2000, n_features=25, n_informative=12, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# ===== 1. Random Forest =====
rf = RandomForestClassifier(
    n_estimators=200,    # 트리 개수
    max_depth=10,        # 최대 깊이
    min_samples_leaf=2,  # 리프 최소 샘플
    max_features="sqrt",  # 분기 시 고려 피처 수 (sqrt = 현업 표준)
    n_jobs=-1,           # 모든 CPU 사용
    random_state=42,
    oob_score=True       # Out-of-Bag 점수 (추가 검증)
)
rf.fit(X_train, y_train)
print(f"RF 정확도: {rf.score(X_test, y_test):.4f}")
print(f"OOB 점수:  {rf.oob_score_:.4f}")

# ===== 2. 피처 중요도 시각화 (현업 필수!) =====
feat_importance = pd.Series(rf.feature_importances_,
                            index=[f"f{i}" for i in range(25)])
feat_importance = feat_importance.sort_values(ascending=False)[:10]

plt.figure(figsize=(10, 5))
feat_importance.plot(kind="barh", color="#6c5ce7")
plt.title("Random Forest 피처 중요도 TOP 10", fontsize=14)
plt.xlabel("중요도")
plt.tight_layout()
plt.show()

# ===== 3. XGBoost — 현업 1등 알고리즘 =====
# pip install xgboost
import xgboost as xgb

xgb_model = xgb.XGBClassifier(
    n_estimators=300,
    learning_rate=0.05,   # 낮을수록 정밀, 트리 더 필요
    max_depth=6,
    subsample=0.8,       # 행 샘플링 비율
    colsample_bytree=0.8,# 열 샘플링 비율
    reg_alpha=0.1,       # L1 정규화
    reg_lambda=1.0,      # L2 정규화
    use_label_encoder=False,
    eval_metric="logloss",
    random_state=42,
    n_jobs=-1
)
xgb_model.fit(
    X_train, y_train,
    eval_set=[(X_test, y_test)],
    verbose=50  # 50 라운드마다 점수 출력
)
print(f"XGBoost 정확도: {xgb_model.score(X_test, y_test):.4f}")

# ===== 4. LightGBM — XGBoost보다 빠름 =====
# pip install lightgbm
import lightgbm as lgb

lgb_model = lgb.LGBMClassifier(n_estimators=300, learning_rate=0.05,
                               num_leaves=31, random_state=42)
lgb_model.fit(X_train, y_train)
print(f"LightGBM 정확도: {lgb_model.score(X_test, y_test):.4f}")

# ===== 5. 보팅 앙상블 =====
voting = VotingClassifier(
    estimators=[
        ("rf", rf),
        ("xgb", xgb_model),
        ("lgb", lgb_model),
    ],
    voting="soft"  # 확률 평균 (hard는 다수결)
)
voting.fit(X_train, y_train)
print(f"Voting 앙상블: {voting.score(X_test, y_test):.4f}")

📈 Chapter 04. 회귀 알고리즘 완전 정복

선형 회귀 · 릿지 · 라쏘 · ElasticNet — 수치 예측의 모든 것

📊 회귀 알고리즘 비교

모델명 특징 정규화 피처선택 언제쓰나
선형 회귀 최소제곱법 없음 안함 기준선 모델
Ridge (L2) 계수 크기 페널티 L2 안함 다중공선성
Lasso (L1) 계수를 0으로 수렴 L1 자동 피처선택 필요
ElasticNet L1+L2 혼합 L1+L2 부분 고차원 데이터
from sklearn.linear_model import LinearRegression, Ridge, Lasso, ElasticNet
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.datasets import make_regression, fetch_california_housing
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.model_selection import train_test_split
import numpy as np

X, y = make_regression(n_samples=1000, n_features=20, noise=15, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

regressors = {
    "LinearReg": LinearRegression(),
    "Ridge(1)": Ridge(alpha=1.0),
    "Lasso(0.1)": Lasso(alpha=0.1),
    "ElasticNet": ElasticNet(alpha=0.1, l1_ratio=0.5),
}

for name, reg in regressors.items():
    reg.fit(X_train, y_train)
    y_pred = reg.predict(X_test)
    rmse = np.sqrt(mean_squared_error(y_test, y_pred))
    r2 = r2_score(y_test, y_pred)
    print(f"{name}: RMSE={rmse:.2f}, R2={r2:.4f}")

# ===== 다항 회귀 Pipeline =====
poly_pipeline = Pipeline([
    ("scaler", StandardScaler()),
    ("poly",   PolynomialFeatures(degree=2, include_bias=False)),
    ("ridge",  Ridge(alpha=10.0)),
])
poly_pipeline.fit(X_train, y_train)
print(f"다항 R2: {poly_pipeline.score(X_test, y_test):.4f}")

# 캘리포니아 주택 가격 예측
housing = fetch_california_housing()
Xh, yh = housing.data, housing.target
Xh_tr, Xh_te, yh_tr, yh_te = train_test_split(Xh, yh, test_size=0.2, random_state=42)
pipeline = Pipeline([("scaler", StandardScaler()), ("ridge", Ridge(alpha=1.0))])
pipeline.fit(Xh_tr, yh_tr)
print(f"주택가격 Ridge R2: {pipeline.score(Xh_te, yh_te):.4f}")

# ===== Lasso 피처 선택 효과 확인 =====
lasso = Lasso(alpha=0.5)
lasso.fit(X_train, y_train)
zero_count = (lasso.coef_ == 0).sum()
print(f"Lasso가 0으로 만든 피처: {zero_count}개 / 20개")

🔵 Chapter 05. 클러스터링 (비지도학습) 완전 정복

K-Means · DBSCAN · PCA · t-SNE — 레이블 없는 데이터 분석

from sklearn.cluster import KMeans, DBSCAN
from sklearn.decomposition import PCA
from sklearn.datasets import make_blobs, make_moons, load_digits
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
import numpy as np

X, _ = make_blobs(n_samples=500, centers=4, cluster_std=0.8, random_state=42)

# ===== 엘보우 + 실루엣으로 최적 K 찾기 =====
inertias, silhouettes = [], []
for k in range(2, 11):
    km = KMeans(n_clusters=k, random_state=42, n_init=10)
    km.fit(X)
    inertias.append(km.inertia_)
    silhouettes.append(silhouette_score(X, km.labels_))

fig, axes = plt.subplots(1, 2, figsize=(12, 4))
axes[0].plot(range(2,11), inertias, "b-o")
axes[0].set_title("엘보우 방법")
axes[1].plot(range(2,11), silhouettes, "r-s")
axes[1].set_title("실루엣 점수")
plt.show()

# ===== DBSCAN — 밀도 기반 (비선형 클러스터) =====
X_moon, _ = make_moons(n_samples=300, noise=0.1)
dbscan = DBSCAN(eps=0.2, min_samples=5)
db_labels = dbscan.fit_predict(X_moon)
print(f"DBSCAN 클러스터 수: {len(set(db_labels)) - (1 if -1 in db_labels else 0)}")
print(f"이상치 수: {(db_labels == -1).sum()}")

# ===== PCA — 차원 축소 =====
digits = load_digits()  # 8x8=64 차원 손글씨
pca = PCA(n_components=2)
X_pca = pca.fit_transform(digits.data)  # 64 → 2차원
print(f"2PC 설명 분산: {pca.explained_variance_ratio_.sum():.1%}")

pca_full = PCA().fit(digits.data)
cumvar = pca_full.explained_variance_ratio_.cumsum()
min_pc = (cumvar >= 0.95).argmax() + 1
print(f"95% 분산 보존 PC 수: {min_pc}")

📏 Chapter 06. 모델 평가 완전 정복

Accuracy, Precision, Recall, F1, ROC-AUC, Cross-Validation — 모델을 제대로 평가하는 법

🎯 분류 모델 평가 지표 완전 이해

혼동 행렬(Confusion Matrix) 기반 용어
TP(참 긍정) | FP(거짓 긍정, 1종 오류) | FN(거짓 부정, 2종 오류) | TN(참 부정)

지표 수식 의미 중요 상황
Accuracy (TP+TN)/(전체) 전체 정확률 균형 데이터
Precision TP/(TP+FP) 예측 긍정 중 실제 긍정 FP 비용 높을 때 (스팸)
Recall TP/(TP+FN) 실제 긍정 중 예측 성공 FN 비용 높을 때 (암 진단)
F1-Score 2*P*R/(P+R) Precision·Recall 조화평균 불균형 데이터
ROC-AUC ROC 곡선 면적 임계값 무관한 전체 성능 이진 분류 종합 평가
RMSE sqrt(MSE) 예측 오차 (원 단위) 회귀 주요 지표
from sklearn.metrics import (
    accuracy_score, precision_score, recall_score, f1_score,
    roc_auc_score, roc_curve, confusion_matrix, classification_report
)
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
import seaborn as sns
import matplotlib.pyplot as plt

X, y = make_classification(n_samples=1000, weights=[0.8, 0.2], random_state=42)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, random_state=42)

rf = RandomForestClassifier(random_state=42)
rf.fit(X_tr, y_tr)
y_pred = rf.predict(X_te)
y_proba = rf.predict_proba(X_te)[:,1]

print(f"Accuracy:  {accuracy_score(y_te, y_pred):.4f}")
print(f"Precision: {precision_score(y_te, y_pred):.4f}")
print(f"Recall:    {recall_score(y_te, y_pred):.4f}")
print(f"F1:        {f1_score(y_te, y_pred):.4f}")
print(f"ROC-AUC:   {roc_auc_score(y_te, y_proba):.4f}")

# ROC 곡선
fpr, tpr, _ = roc_curve(y_te, y_proba)
plt.figure(figsize=(7,5))
plt.plot(fpr, tpr, label=f"AUC = {roc_auc_score(y_te, y_proba):.3f}")
plt.plot([0,1],[0,1], "--", color="gray", label="랜덤 분류기")
plt.title("ROC Curve")
plt.xlabel("FPR")
plt.ylabel("TPR")
plt.legend()
plt.show()

# ===== 교차 검증 — 모델 신뢰성 검증 =====
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
cv_scores = cross_val_score(rf, X, y, cv=skf, scoring="f1", n_jobs=-1)
print(f"5-Fold CV F1: {cv_scores.mean():.4f} +/- {cv_scores.std():.4f}")

🔧 Chapter 07. 하이퍼파라미터 튜닝 완전 정복

GridSearch · RandomSearch · Optuna — 모델 성능을 끌어올리는 체계적 방법

from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from scipy.stats import randint, uniform

X, y = make_classification(n_samples=1500, random_state=42)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, random_state=42)

# ===== 1. GridSearchCV — 모든 조합 탐색 =====
param_grid = {
    "n_estimators":  [100, 200, 300],
    "max_depth":    [5, 10, None],
    "min_samples_leaf": [1, 2, 4],
}
grid_search = GridSearchCV(
    RandomForestClassifier(random_state=42), param_grid,
    cv=5, scoring="f1", n_jobs=-1, verbose=1
)
grid_search.fit(X_tr, y_tr)
print(f"GridSearch 최적 파라미터: {grid_search.best_params_}")
print(f"GridSearch 최고 F1: {grid_search.best_score_:.4f}")

# ===== 2. RandomizedSearchCV — 대규모 파라미터 공간 =====
param_dist = {
    "n_estimators":   randint(50, 500),
    "max_depth":      randint(3, 20),
    "max_features":   uniform(0.3, 0.7),
    "min_samples_leaf": randint(1, 10),
}
rand_search = RandomizedSearchCV(
    RandomForestClassifier(random_state=42), param_dist,
    n_iter=30, cv=5, scoring="f1", n_jobs=-1, random_state=42
)
rand_search.fit(X_tr, y_tr)
print(f"RandomSearch 최적 파라미터: {rand_search.best_params_}")

# ===== 3. Optuna — 베이지안 최적화 (최신 방법) =====
# pip install optuna
import optuna
optuna.logging.set_verbosity(optuna.logging.WARNING)

def objective(trial):
    n_est = trial.suggest_int("n_estimators", 50, 500)
    depth = trial.suggest_int("max_depth", 3, 20)
    leaf = trial.suggest_int("min_samples_leaf", 1, 10)
    rf_opt = RandomForestClassifier(n_estimators=n_est, max_depth=depth,
                                   min_samples_leaf=leaf, random_state=42)
    return cross_val_score(rf_opt, X_tr, y_tr, cv=3, scoring="f1").mean()

study = optuna.create_study(direction="maximize")
study.optimize(objective, n_trials=30, show_progress_bar=True)
print(f"Optuna 최적값: {study.best_params}")
print(f"Optuna 최고 F1: {study.best_value:.4f}")

⚙️ Chapter 08. Pipeline & 전처리 자동화

ColumnTransformer · Pipeline · joblib — 현업 수준 ML 코드 구조

💡 Pipeline이 왜 필수인가?

Pipeline 없이 코딩하면 데이터 누수(Data Leakage) 위험이 있습니다. 테스트 데이터의 정보가 학습에 새면 모델이 실제보다 좋아 보이는 착시가 발생합니다. Pipeline은 전처리+모델을 하나의 객체로 묶어 이 문제를 원천 방지합니다.

from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder, LabelEncoder
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split, cross_val_score
import pandas as pd
import numpy as np

# ===== 혼합 타입 데이터 (수치형 + 범주형) =====
np.random.seed(42)
n = 500
df = pd.DataFrame({
    "age":    np.random.randint(20, 70, n),
    "income": np.random.exponential(50000, n),
    "score":  np.random.normal(70, 15, n),
    "city":   np.random.choice(["서울","부산","대구"], n),
    "edu":    np.random.choice(["고졸","대졸","대학원"], n),
})
df.loc[:30, "age"] = np.nan
df.loc[50:80, "city"] = np.nan
y = (df["income"] > df["income"].median()).astype(int)

X = df
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, random_state=42)

# ===== 수치형·범주형 전처리 분리 정의 =====
num_cols = ["age", "income", "score"]
cat_cols = ["city", "edu"]

num_transformer = Pipeline([
    ("imputer", SimpleImputer(strategy="median")),  # 결측값 중앙값 대체
    ("scaler",  StandardScaler()),                   # 표준화
])
cat_transformer = Pipeline([
    ("imputer", SimpleImputer(strategy="most_frequent")),  # 결측값 최빈값
    ("encoder", OneHotEncoder(handle_unknown="ignore", sparse_output=False)),
])

preprocessor = ColumnTransformer([
    ("num", num_transformer, num_cols),
    ("cat", cat_transformer, cat_cols),
])

# ===== 완전한 ML Pipeline =====
full_pipeline = Pipeline([
    ("preprocessor", preprocessor),
    ("classifier",  RandomForestClassifier(n_estimators=100, random_state=42)),
])

full_pipeline.fit(X_tr, y_tr)
print(f"Pipeline 정확도: {full_pipeline.score(X_te, y_te):.4f}")

cv = cross_val_score(full_pipeline, X, y, cv=5, scoring="accuracy")
print(f"5-Fold CV: {cv.mean():.4f} +/- {cv.std():.4f}")

# ===== 모델 저장 & 불러오기 =====
import joblib

joblib.dump(full_pipeline, "ml_pipeline.pkl")  # 저장
loaded = joblib.load("ml_pipeline.pkl")        # 불러오기
print(f"로드 후 정확도: {loaded.score(X_te, y_te):.4f}")

🏆 Chapter 09. 실전 — 타이타닉 End-to-End ML

EDA → 전처리 → 모델 선택 → 튜닝 → 평가 → 예측 — 완전한 ML 프로젝트 경험

import pandas as pd, numpy as np
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score, GridSearchCV
from sklearn.metrics import classification_report

url = "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"
df = pd.read_csv(url)

# 피처 엔지니어링
df["FamilySize"] = df["SibSp"] + df["Parch"] + 1
df["IsAlone"] = (df["FamilySize"] == 1).astype(int)
df["Title"] = df["Name"].str.extract("([A-Za-z]+)\.")
df["Title"] = df["Title"].replace(
    ["Lady","Countess","Capt","Col","Don","Dr",
     "Major","Rev","Sir","Jonkheer","Dona"], "Rare")
df["Title"] = df["Title"].replace(["Mlle","Ms"], "Miss").replace("Mme", "Mrs")

features = ["Pclass","Sex","Age","Fare","Embarked","FamilySize","IsAlone","Title"]
X = df[features]
y = df["Survived"]

num_feats = ["Age","Fare","FamilySize","IsAlone"]
cat_feats = ["Pclass","Sex","Embarked","Title"]

num_tf = Pipeline([("imp", SimpleImputer(strategy="median")), ("scl", StandardScaler())])
cat_tf = Pipeline([("imp", SimpleImputer(strategy="most_frequent")),
                   ("enc", OneHotEncoder(handle_unknown="ignore", sparse_output=False))])
preproc = ColumnTransformer([("n", num_tf, num_feats), ("c", cat_tf, cat_feats)])

pipeline = Pipeline([("prep", preproc), ("clf", RandomForestClassifier(random_state=42))])

# 그리드 서치
param_grid = {"clf__n_estimators": [100,200], "clf__max_depth": [5,10,None]}
gs = GridSearchCV(pipeline, param_grid, cv=5, scoring="accuracy", n_jobs=-1)
gs.fit(X, y)
print(f"타이타닉 최고 CV 정확도: {gs.best_score_:.4f}")
print(f"최적 파라미터: {gs.best_params_}")

🎯 Chapter 10. 현업 면접 질문과 답변 TOP 10

머신러닝 개발자 취업 면접 빈출 질문과 완벽 모범 답변

Q1. Bias(편향)와 Variance(분산)의 트레이드오프란?

A: Bias는 모델이 실제 패턴을 단순화해서 생기는 오류(과소적합)이고, Variance는 학습 데이터에 과도하게 맞춰 새 데이터에 일반화가 안 되는 오류(과적합)입니다. 복잡한 모델일수록 Bias 낮고 Variance 높아집니다. 해결: ① 과적합 시 — 데이터 증가, 정규화, Dropout, 모델 단순화, Cross-Val ② 과소적합 시 — 모델 복잡도 증가, 피처 추가, 학습 시간 증가. 최적 모델은 두 오류의 합이 최소화되는 지점에 있습니다.

Q2. 교차 검증(Cross-Validation)을 왜 사용하나요?

A: 단순 Train/Test 분리는 데이터 분할 방법에 따라 성능이 달라지는 운의 영향을 받습니다. 교차 검증은 데이터를 K개 폴드로 나눠 K번 학습/검증을 반복해 더 신뢰할 수 있는 성능 추정값을 얻습니다. 종류: K-Fold(일반), StratifiedKFold(불균형 분류), TimeSeriesSplit(시계열). 특히 데이터가 적을 때 Leave-One-Out(n=K)을 쓰기도 합니다. 교차 검증 점수의 평균과 표준편차를 함께 보고해야 합니다.

Q3. Random Forest와 XGBoost의 차이점은?

A: Random Forest는 배깅(Bagging) 방식으로 트리를 독립적으로 병렬 학습합니다. XGBoost는 부스팅(Boosting) 방식으로 이전 트리의 잔차(오류)를 학습해 순차적으로 개선합니다. 성능: XGBoost > Random Forest (대부분의 경우). 속도: Random Forest가 병렬이라 빠를 수 있지만 LightGBM이 XGBoost보다 빠름. 해석성: Random Forest가 약간 더 이해하기 쉬움. 과적합: XGBoost는 정규화 파라미터(reg_alpha, reg_lambda)로 제어 가능.

Q4. 데이터 누수(Data Leakage)란 무엇이며 어떻게 방지하나요?

A: 데이터 누수는 학습 단계에서 테스트/실제 데이터 정보가 모델에 새어 들어가는 현상입니다. 주요 원인: ① 전체 데이터로 StandardScaler fit 후 분리 ② 타겟과 직접 연관된 피처 포함 ③ 미래 데이터가 과거 예측에 사용. 방지: ① 항상 Train에만 fit, Test는 transform만 ② Sklearn Pipeline 사용 ③ 시계열은 미래 데이터 엄격히 분리. 누수가 있으면 검증 성능이 비현실적으로 높게 나옵니다.

Q5. F1-Score를 Accuracy 대신 쓰는 경우는?

A: 클래스 불균형 데이터에서 Accuracy는 오해를 유발합니다. 예: 사기 탐지에서 사기 1% vs 정상 99%이면, 모든 거래를 "정상"으로 예측해도 Accuracy=99%지만 사기를 하나도 잡지 못합니다. F1-Score는 Precision과 Recall의 조화평균으로 소수 클래스 탐지 성능을 종합 평가합니다. 임계값에 무관한 전체 성능은 ROC-AUC로 평가합니다. 의료 진단처럼 FN이 치명적이면 Recall을 우선합니다.

Q6. 피처 중요도(Feature Importance)란?

A: 피처 중요도는 각 입력 변수가 모델 예측에 얼마나 기여하는지 측정합니다. RF/XGBoost는 분기에 사용된 횟수와 불순도 감소량으로 계산합니다. 그러나 이 방법은 카디널리티가 높은 피처를 과대평가하는 편향이 있습니다. 더 신뢰할 수 있는 방법: ① SHAP(SHapley Additive exPlanations) — 게임이론 기반, 개별 예측 설명 가능 ② Permutation Importance — 피처를 섞어 성능 하락 측정. 현업에서 SHAP이 표준이 되어가고 있습니다.

Q7. K-Means에서 최적 K를 어떻게 결정하나요?

A:엘보우 방법(Elbow Method) — K 증가에 따른 Inertia(군집 내 분산) 그래프에서 꺾이는 점 선택. ② 실루엣 점수(Silhouette Score) — -1~1 사이 값으로 높을수록 좋음, 명확한 최대점이 최적 K. ③ Gap Statistic — 랜덤 데이터 대비 클러스터링 품질 비교. ④ 도메인 지식 — 비즈니스적으로 의미 있는 K 선택. 실무에서는 엘보우+실루엣을 함께 보는 것이 일반적입니다.

Q8. 로지스틱 회귀와 선형 회귀의 차이는?

A: 선형 회귀는 연속형 수치를 예측하고, 로지스틱 회귀는 클래스 확률(0~1)을 예측합니다. 로지스틱 회귀는 선형 결합에 시그모이드 함수(σ(z)=1/(1+e^-z))를 적용해 확률로 변환합니다. 손실함수도 다릅니다: 선형 회귀는 MSE(최소제곱), 로지스틱 회귀는 Binary Cross-Entropy(로그 손실)를 최소화합니다. 이름에 "회귀"가 있지만 분류 알고리즘입니다.

Q9. SVM의 커널 트릭이란?

A: SVM은 클래스를 구분하는 최대 마진 초평면을 찾습니다. 데이터가 선형으로 분리 불가능할 때 커널 트릭을 사용합니다. 커널 함수는 데이터를 실제로 고차원으로 변환하지 않고, 고차원에서의 내적값만 계산해 계산 효율을 유지합니다. RBF(가우시안) 커널이 가장 많이 사용됩니다. C 파라미터: 마진과 오분류 허용의 균형 (클수록 강한 분류). gamma: RBF 커널의 영향 범위 (클수록 좁아짐).

Q10. 현업에서 ML 프로젝트는 어떻게 진행되나요?

A: 표준 ML 프로젝트 흐름: ① 문제 정의 — 비즈니스 목표, 성공 지표(KPI) 설정 ② 데이터 수집·EDA — 데이터 이해, 품질 확인 ③ 피처 엔지니어링 — 변수 변환, 새 피처 생성 ④ 모델 선택·학습 — 기준선부터 복잡한 모델로 ⑤ 평가·튜닝 — Cross-Val, HyperParam 최적화 ⑥ 해석·검증 — SHAP, A/B 테스트 ⑦ 배포·모니터링 — FastAPI, Docker, 성능 모니터링. 실무에서는 빠른 기준선 모델(Baseline)을 먼저 만들고 점진적으로 개선합니다.

✅ AiDevGuide0004 완료 체크리스트

📗 ML 기초

  • ✅ ML 워크플로 이해
  • ✅ Scikit-learn API 패턴
  • ✅ 분류 알고리즘 4종
  • ✅ 앙상블 (RF, XGBoost)

📘 ML 중급

  • ✅ 회귀 알고리즘 (Ridge, Lasso)
  • ✅ 클러스터링 + PCA
  • ✅ 모델 평가 지표
  • ✅ 교차 검증

📕 ML 고급

  • ✅ GridSearch / Optuna 튜닝
  • ✅ Pipeline + ColumnTransformer
  • ✅ 모델 저장 (joblib)
  • ✅ SHAP 피처 중요도

🏆 실전 프로젝트

  • 타이타닉 E2E ML 구현
  • Kaggle 제출 경험
  • 면접 Q&A 10개 숙지
  • GitHub 포트폴리오 업로드
🤖

AiDevGuide0004 완료!

머신러닝을 완전히 정복했습니다!
이제 분류·회귀·클러스터링 모델을 직접 만들 수 있습니다 💪

10 Chapters 완료면접 Q&A TOP 10타이타닉 E2E 실전

🚀 다음 단계: AiDevGuide0005

TensorFlow·PyTorch로 딥러닝 완전 정복!

반응형