분류와 군집화

교재 9장. 분류(classification) 는 정답 라벨을 학습하는 지도학습, 군집화(clustering) 는 라벨 없이 비슷한 것끼리 묶는 비지도학습. 로지스틱 회귀 → k-NN → k-평균까지.


1. 분류 vs 군집화

분류 (classification)군집화 (clustering)
학습 방식지도학습 (라벨 있음)비지도학습 (라벨 없음)
목표새 데이터의 클래스 예측데이터를 비슷한 군집으로 묶기
로지스틱 회귀, k-NN, SVM, 결정트리k-평균, 계층 군집
출력미리 정의된 범주데이터로부터 발견된 그룹

2. 로지스틱 회귀 — 분류를 위한 회귀

선형 회귀의 출력은 확률(0~1) 로 쓸 수 없습니다. 그래서 시그모이드 함수로 짓눌러 확률로 만듭니다.

  • 출력 → "클래스 1일 확률"로 해석
  • 결정 경계: 이면 1, 아니면 0

2.1 시그모이드와 지수의 관계

좌변은 오즈(odds). 로그를 취하면 — 즉 로지스틱 회귀는 로그 오즈가 선형인 모델입니다.

2.2 교차 엔트로피 손실

분류에는 MSE 대신 교차 엔트로피(cross entropy) 를 씁니다.

  • 정답이 1인데 가 0에 가까우면 손실 폭발 → 강하게 벌점
  • 학습 = 이 손실을 최소화하는 찾기 (경사 하강법)

로지스틱 회귀 — 시그모이드와 결정 경계

Ch.09
10점수 x경계
클래스 0 (불합격)
클래스 1 (합격)
σ(wx+b)
1.4
-7.0
결정 경계 x
5.00
교차엔트로피 손실
0.090
정확도
100%
w, b 를 조절해 손실이 최소가 되는 곡선을 찾아보세요. w 가 클수록 곡선이 가팔라져 (확신이 강해짐), b 는 결정 경계 x = -b/w 를 좌우로 옮깁니다. 로지스틱 회귀의 학습 = 교차엔트로피 손실을 최소화하는 w, b 찾기입니다.

3. k-NN — 가까운 이웃으로 분류

k-최근접 이웃(k-Nearest Neighbors): 새 데이터에서 가장 가까운 k개 이웃의 다수결로 클래스를 정함.

PYTHON
from sklearn.neighbors import KNeighborsClassifier
 
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)          # 사실상 "데이터를 저장"만 함 (게으른 학습)
knn.predict(X_new)
  • 학습 비용 거의 0, 예측 시 모든 거리 계산 → 예측이 느림 (게으른 학습자, lazy learner)
  • k 가 작으면 노이즈에 민감(과적합), 크면 경계가 뭉툭(과소적합)
  • 붓꽃(iris) 데이터: 꽃받침/꽃잎 길이·너비 4특성 → 3품종 분류의 고전 예제

3.1 거리 기반 알고리즘엔 스케일링이 필수

PYTHON
from sklearn.preprocessing import StandardScaler, MinMaxScaler
 
ss = StandardScaler()                 # 평균 0, 표준편차 1
X_train_ss = ss.fit_transform(X_train)
X_test_ss  = ss.transform(X_test)     # ← test 는 transform 만!
스케일러변환특징
StandardScaler평균 0·표준편차 1. 가장 일반적
MinMaxScaler0~1 범위. 이상치에 민감
RobustScaler중앙값·IQR 사용이상치에 강건

주의: 스케일러는 훈련 데이터로만 fit. 테스트에 fit_transform 하면 데이터 누수(data leakage).


4. k-평균 군집화 (k-means)

라벨 없이 데이터를 k개 군집으로 묶는 비지도 알고리즘. 두 단계를 번갈아 반복:

  1. ① 할당: 각 점을 가장 가까운 군집 중심(centroid) 에 배정
  2. ② 갱신: 각 군집의 평균 위치로 중심을 이동

중심이 더 이상 움직이지 않으면 수렴. 목적함수는 inertia(군집 내 거리 제곱합):

PYTHON
from sklearn.cluster import KMeans
 
km = KMeans(n_clusters=3, n_init=10, random_state=0)
labels = km.fit_predict(X)
km.cluster_centers_     # 군집 중심 좌표
km.inertia_             # 군집 내 분산 합 (작을수록 조밀)

k-평균 군집화 — 할당 ↔ 갱신 반복

Ch.09
① 할당 — 각 점을 가장 가까운 중심에 배정(iter 3)
3
단계
7 / 7
군집 수
3
inertia (군집내 분산)
0.192
초기 중심을 바꿔보세요(🎲). 같은 데이터라도 시작점에 따라 다른 군집으로 수렴할 수 있습니다 (지역 최솟값 문제). 그래서 sklearn 의 KMeansn_init 번 반복해 가장 inertia 가 작은 결과를 고릅니다. 진짜 군집이 3개인데 k 를 바꾸면 어떻게 망가지는지도 확인해 보세요.
→ 더 깊은 인터랙티브: Visualizing K-Means (naftaliharris)

4.1 초기값 민감성과 n_init

k-평균은 초기 중심에 따라 다른 결과로 수렴할 수 있습니다(지역 최솟값). n_init=10 은 서로 다른 초기값으로 10번 돌려 inertia 가 가장 작은 결과를 채택합니다.


5. 결정 트리 — ID3 · CART

스무고개처럼 질문(분기) 을 반복해 데이터를 나누는 분류기. 각 분기는 불순도가 가장 많이 줄어드는 특성·기준을 고릅니다.

5.1 엔트로피와 정보 이득 (ID3) — 시험 제외

📌 ID3(엔트로피·정보 이득)는 이번 시험 범위에서 제외됩니다. 개념만 가볍게 참고하세요.

엔트로피: 데이터가 얼마나 섞여 있는지(불순도).

  • 한 클래스만 있으면 (순수), 반반이면 (최대 혼란)
  • 정보 이득 = 분기 전 엔트로피 − 분기 후 가중평균 엔트로피. ID3 는 정보 이득이 최대인 분기를 선택.

5.2 지니 불순도 ⭐

CART(Classification And Regression Tree)는 분기 기준으로 지니 불순도를 씁니다.

  • 한 클래스만 있으면 (순수), 클래스가 고르게 섞일수록 커짐 (2클래스 최대 0.5)
  • 엔트로피와 거동은 비슷하지만 로그가 없어 계산이 빠름 → 사이킷런 DecisionTreeClassifier 기본값

5.3 CART 알고리즘 ⭐ — 시험 범위

CART 는 재귀적 이진 분할(recursive binary splitting) 로 트리를 키웁니다. 한 노드를 나눌 때:

  1. 모든 후보 분할 생성 — 각 특성 × 각 임계값 조합마다 "특성 ≤ t ?" 라는 예/아니오 분할 후보를 만든다 (CART 는 항상 이진 분기)

  2. 각 분할의 비용 = 자식 노드들의 가중 지니 불순도

  3. 지니 이득(Gini gain) 이 가장 큰 = 가중 불순도가 가장 작은 분할을 선택

  4. 나뉜 두 자식 노드에 대해 1~3을 재귀 반복

  5. 정지 조건 에 닿으면 멈추고 잎(leaf)으로: 노드가 순수(), max_depth 도달, min_samples_split 미만, 더 이상 이득 없음

ID3 의 "정보 이득(엔트로피)" 자리를 CART 에선 "지니 이득"이 대신한다고 보면 됩니다. 구조는 같고 불순도 척도만 다름.

손으로 푸는 예제

부모 노드 10개 (양성 5, 음성 5):

"특성 X ≤ 3 ?" 으로 나눴더니 — 왼쪽 5개(양성4·음성1), 오른쪽 5개(양성1·음성4):

→ 이득 0.18. 다른 모든 분할 후보와 비교해 ΔG 가 최대인 것을 이 노드의 분기로 채택합니다.

PYTHON
from sklearn.tree import DecisionTreeClassifier
 
# criterion 기본값이 'gini' → CART
tree = DecisionTreeClassifier(criterion='gini', max_depth=3)
tree.fit(X_train, y_train)
  • max_depth 를 제한하지 않으면 과적합(잎이 데이터 하나하나에 맞춰짐) → 가지치기(pruning)·깊이 제한으로 완화
  • 회귀 트리: CART 는 분류뿐 아니라 회귀도 가능. 이때는 지니 대신 MSE 감소량을 분할 기준으로 씀 (이름의 'R' = Regression)
  • 여러 트리를 묶는 앙상블(랜덤 포레스트·부스팅)Ch.10 에서 다룹니다.

6. 혼동행렬과 분류 성능평가

분류 모델은 정확도(accuracy)만으로 평가하면 안 됩니다. 암 환자 1% 데이터에서 "전부 정상"이라 찍어도 정확도 99% → 정작 환자는 다 놓침.

예측 양성예측 음성
실제 양성TP (참 양성)FN (놓침)
실제 음성FP (오경보)TN (참 음성)
  • 정밀도(Precision): 양성이라 한 것 중 진짜 양성 → 오경보가 싫을 때(스팸 분류)
  • 재현율(Recall): 실제 양성 중 잡아낸 비율 → 놓치면 안 될 때(암 진단)
  • F1: 정밀도·재현율의 조화평균 — 둘의 균형

손으로 푸는 계산 예제 ⭐

혼동행렬이 다음과 같이 주어졌다고 하자 (전체 100개):

예측 양성예측 음성
실제 양성TP = 40FN = 20
실제 음성FP = 10TN = 30

차례로 대입:

계산 순서 팁: ① 표에서 TP·FP·FN·TN 위치부터 정확히 읽기 → ② P, R 먼저 → ③ 그 둘로 F1. F1 은 조화평균이라 항상 P·R 사이의 작은 쪽에 가깝게 나온다는 점으로 검산.

혼동 행렬과 정밀도·재현율·F1

Ch.11
임계 0.50← 예측 음성예측 양성 →
실제 양성
실제 음성
30
TP (참 양성)
4
FP (거짓 양성·오경보)
10
FN (거짓 음성·놓침)
36
TN (참 음성)
0.50
정밀도 P
0.88
재현율 R
0.75
F1
0.81
정확도
0.82
임계값을 낮추면 양성 예측이 늘어 재현율↑ 정밀도↓ (놓침은 줄지만 오경보 증가), 높이면 반대가 됩니다. 둘은 트레이드오프 관계이고, F1 은 둘의 조화평균이라 균형 지점에서 최대가 됩니다. 암 진단처럼 놓치면 치명적인 문제는 재현율을, 스팸 분류처럼 오경보가 거슬리는 문제는 정밀도를 중시합니다.
PYTHON
from sklearn.metrics import classification_report, confusion_matrix
 
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))   # P·R·F1 한 번에

교차검증·엘보우 등 더 깊은 성능평가Ch.11 튜닝과 성능평가 참고.


7. 특성 공학 (Feature Engineering)

모델 성능은 알고리즘보다 좋은 특성에서 더 크게 갈립니다. 원본 데이터를 모델이 잘 학습하도록 가공하는 작업.

기법설명
스케일링단위가 다른 특성을 같은 범위로StandardScaler, MinMaxScaler
인코딩범주형 → 수치형원-핫 인코딩(pd.get_dummies), 라벨 인코딩
결측 처리빈 값 채우기/제거평균·중앙값 대치, dropna
특성 생성기존 특성 조합으로 새 특성BMI = 체중/키², 다항 특성
특성 선택불필요한 특성 제거상관도 기반, 라쏘(L1)
PYTHON
# 범주형 원-핫 인코딩
df = pd.get_dummies(df, columns=['city', 'grade'])
 
# 거리·규제 기반 모델엔 스케일링 필수
from sklearn.preprocessing import StandardScaler
X_scaled = StandardScaler().fit_transform(X)
  • "Garbage In, Garbage Out" — 좋은 특성이 좋은 모델을 만든다
  • 라쏘(L1) 규제는 계수를 0으로 만들어 자동 특성 선택 효과 (Ch.8 참고)

📝 Checkpoint

Quiz

분류와 군집화 Checkpoint

Q 1 / 15

로지스틱 회귀에서 시그모이드 함수를 쓰는 이유로 가장 적절한 것은?


🔗 이어서