AI/머신러닝

실무에 쓰는 머신러닝 기초 1주차 (비지도 학습 & 클러스터링)

edcrfv458 2025. 3. 19. 14:52

목표

  • 비지도 학습 개념
  • 군집 분석의 기본 원리와 활용 알고리즘
  • 군집 분석 평가 방법

 

1. 비지도 학습 개요

  • 정답 값 없이 데이터에서 패턴이나 구조를 찾는 머신러닝 기법

 

활용 영역

  • 데이터의 군집화(Clustering)
  • 차원 축소(Dimensionality Reduction)
  • 이상치 탐지(Anomlay Detection)

 

지도 학습과의 비교

  • 비지도 학습에서는 라벨 대신 데이터 자체의 유사성과 패턴에 집중

 

2. 군집 분석의 개념

  • 비슷한 특성을 가진 데이터들을 묶어 각 그룹 내 데이터들끼리의 유사도를 최대화하고, 다른 그룹과의 차이는 최대화하는 기법

 

목적

  • 데이터의 구조 파악: 정답 없이 데이터의 자연스러운 분포를 확인
  • 세분화(Segmentation): 마케팅에서는 고객 세분화를, 제조업에서는 센서 데이터로 기계 작동 패턴 분류 등을 수행

 

군집 분석의 절차

  1. 데이터 수집 밎 전처리: 이상치 제거, 결측치 처리, 스케일링/정규화
  2. 군집 수 또는 파라미터 설정: K-Means의 경우 k 설정, DBSCAN은 거리(앱실론), 최소 데이터 수(minPts) 등
  3. 군집화 알고리즘 적용: 설정에 따라 알고리즘 수행
  4. 결과 해석 및 평가: 실루엣 계수 등 군집 평가 지표 활용
  5. 사후 활용: 마케팅 전략, 제품 개선, 이상치 탐지 등

 

3. 주요 군집 분석 알고리즘

 

K-Means

  • 알고리즘 개요
    • 미리 군집 수 k를 지정해야 함
    • 무작위로 k개의 중심(centroid)을 선택 후, 각 데이터 포인트를 가장 가까운 중심에 할당
    • 각 군집의 중심을 다시 계산하고 재할당하는 과정을 반복
    • 군집 내 데이터와 중심 간 거리의 제곱합을 최소화
  • 장점
    • 계산 속도가 빠르고 구현이 간단
    • 대용량 데이터에도 비교작 잘 작동
  • 단점
    • 군집 수 k를 미리 알아야 함
    • 이상치에 취약(중심 값에 영향을 미침)
    • 구형 구조가 아닌 복잡한 형태의 분포를 파악하기 어려움
      • 구형: 원형
  • 예시
    • 고객 데이터를 나이, 월평균 지출액, 자주 구매하는 카테고리(One-hot 인코딩 후 스케일링 적용) 등을 가지고 분석
    • k=3으로 설정한다며 "저가 위주의 고객", "중간 가격대 선호 고객", "고가 제품 위주 고객" 등으로 군집이 나뉠 수 있음

 

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)

  • 알고리즘 개요
    • 밀도 기반 군집화 기법
    • 일정 거리 내 데이터가 많으면(최소 포인트 수 minPts 이상) 그 영역을 밀도가 높다고 판단해 하나의 군집으로 결정
    • k를 미리 설정하지 않아도 되며 노이즈 포인트를 구분할 수 있음
  • 장점
    • 군집 수를 사전에 알 필요가 없음
    • 이상치와 노이즈를 자연스럽게 처리
    • 구형이 아닌 복잡한 형태의 군집도 잘 찾아냄
  • 단점
    • 파라미터 거리(앱실론)최소 포인트 수(minPts)에 민감
    • 데이터가 밀도가 균일하지 않으면 성능이 떨어질 수 있음
  • 예시
    • 지리 정보(GIS) 분석에서 지역별로 가게가 얼마나 밀집되어 있는지 분석할 때 사용
    • 특정 지점에 가게가 몰려 있으면 하나의 군집, 중간에 뜨문뜨문 있는 가게는 노이즈로 분류

 

계층적 클러스터링

  • 알고리즘 개요
    • 데이터 포인트 각각이 하나의 군집으로 시작 ➡️ 유사도가 가장 높은 군집들끼리 병합 ➡️ 최종적으로 하나의 군집(트리) 형성
    • 또는 하나의 군집에서 시작해 분할해 나가는 방법도 존재(분할적 접근)
    • 덴드로그램(Dendogram)으로 시각화 가능
  • 장점
    • 군집의 계층적 구조 파악이 쉬움(덴드로그램)
    • 군집 수를 명확히 결정하지 않아도, 덴드로그램의 특정 높이(cut)에 따라 유연하게 군집 개수 결정 가능
  • 단점
    • 계산 복잡도가 높아 대규모 데이터에 적용이 어려움
  • 예시
    • 유전자 데이터 분석, 유전자 발현 패턴이 유사한 것끼리 계층적으모로 묶어 생물학적 특성을 추론
    • 다양한 문서(텍스트), 클러스터링에서 단어의 사용 빈도 등을 기반으로 문서 구조 시각화

 

코드

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.datasets import load_iris
from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering
from sklearn.model_selection import train_test_split
from sklearn.metrics import silhouette_score
from sklearn.decomposition import PCA

# 1. 데이터 로드
iris = load_iris()
X = iris.data
y = iris.target  # 실제 품종 레이블(군집 학습 자체에는 사용하지 않음)


# 3. K-Means
kmeans = KMeans(n_clusters=3, random_state=42)
kmeans_labels = kmeans.fit_predict(X)

# 4. DBSCAN
dbscan = DBSCAN(eps=0.5, min_samples=5)
dbscan_labels = dbscan.fit_predict(X)

# 5. 계층적 클러스터링 (AgglomerativeClustering)
agg = AgglomerativeClustering(n_clusters=3)
agg_labels = agg.fit_predict(X)

# 6. 각 군집 결과의 실루엣 지수 평가
kmeans_sil = silhouette_score(X, kmeans_labels)
dbscan_sil = silhouette_score(X, dbscan_labels)
agg_sil = silhouette_score(X, agg_labels)

print("=== 군집 결과 비교 ===")
print("K-Means: 실루엣 점수 =", kmeans_sil, "| 클러스터 라벨 =", np.unique(kmeans_labels))
print("DBSCAN: 실루엣 점수 =", dbscan_sil, "| 클러스터 라벨 =", np.unique(dbscan_labels))
print("Agglomerative: 실루엣 점수 =", agg_sil, "| 클러스터 라벨 =", np.unique(agg_labels))

# 7. 시각화를 위해 PCA로 차원 축소 (2차원)
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)

# 8. 군집 결과 시각화
fig, axes = plt.subplots(1, 3, figsize=(15, 4))

# K-Means 시각화
axes[0].scatter(X_pca[:, 0], X_pca[:, 1], c=kmeans_labels)
axes[0].set_title("K-Means")

# DBSCAN 시각화
axes[1].scatter(X_pca[:, 0], X_pca[:, 1], c=dbscan_labels)
axes[1].set_title("DBSCAN")

# Agglomerative 시각화
axes[2].scatter(X_pca[:, 0], X_pca[:, 1], c=agg_labels)
axes[2].set_title("Agglomerative")

plt.tight_layout()
plt.show()

 

4. 군집 분석 평가 방법

  • 비지도 학습은 정답이 없기 때문에 군집 평가 지표가 매우 중요

 

실루엣 계수(Silhouette Score)

  • 각 데이터 포인트의 응집도(a)와 분리도(b)를 이용해 계산
    • 응집도(a): 같은 군집 내 데이터와의 평균 거리
    • 분리도(b): 가장 가까운 다른 군집과의 평균 거리
  • 범위
    • -1 ~ 1
      • 1에 가까울수록 해당 데이터가 잘 군집화된 것
      • 0 근처면 군집 경계에 위치
      • 0보다 작으면 잘못된 군집화 가능성

 

Davies-Bouldin Index

  • 군집 내 분산과 군집 간 거리의 비율을 활용
  • 각 군집에 대해 다른 군집과의 거리를 비교하면서 군집끼리 얼마나 겹치는지 측정
  • 범위
  • 0 이상
  • 값이 0에 가까울수록 군집 간 구분이 잘 된 것
  • 값이 커질수록 군집 간 겹침이 많아 군집화 품질이 낮음

 

내부 평가 vs 외부 평가

  • 내부 평가(Internal Evaluation): 데이터 내부의 정보(분산, 거리 등)를 활용해 평가 (실루엣 계수, Davies-Bouldin Index 등)
  • 외부 평가(External Evalutaion): 이미 알려진 레이블(정답)과 군집 결과를 비교(정답이 있을 때만 가능)

 

5. 사례

 

마케팅 - 고객 세분화 후 맞춤형 마케팅

  • 시나리오 예시
    • 대형 온라인 쇼핑몰에서 여러 고객들의 구매 패턴 데이터(평균 구매 금액, 구매 주기, 선호 카테고리) 수집
  • K-Means나 계층적 군집으로 고객을 세 그룹으로 분류
    • 그룹 A: 저가 상품 위주 구매, 주기적으로 소량 구매
    • 그룹 B: 중간 가격대 상품, 꾸준한 구매, 리워드나 할인에 민감
    • 그룹 C: 고가 브랜드 위주 구매, 구매 빈도는 낮지만 1회 결제 금액이 큼
  • 활용 방안
    • 그룹 A에게는 프로모션 쿠폰, 특정 시즌 할인
    • 그룹 B에게는 멤버십 등급 혜택, 꾸준한 재구매를 위한 포인트 적립 강화
  • 그룹 C에게는 프리미엄 서비스, 맞춤형 추천, VIP 전용 이벤트
  • 결과
  • 고객 만족도 상승, 마케팅 비용 절감, 구매 전환율 증가 효과와 기대

 

제조업 - 센서 데이터 군집화와 이상 탐지

  • 시나리오 예시
    • 공장에 설치된 기계에서 주기적으로 측정되는 온도, 진동, 압력 등의 센서 데이터 수집
  • DBSCAN을 이용해 비슷한 작동 패턴의 센서 데이터 군집화
    • 군집 1: 정상 범주(온도와 진동 값이 일정 범위 내)
    • 군집 2: 약간 불안정한 패턴(진동이 가끔 튀는 경우)
    • 노이즈: 완전히 이상치(기계 고장 상태)
  • 활용 방안
    • 불안정 군집이 얼마나 발생하는지 모니터링하여 사정 정비 계획 수립
    • 노이즈로 분류된 이상치를 즉시 점검하여 사고 예방
  • 결과
    • 예지 정비(Predictive Maintenance)를 통해 생산 라인의 다운타임 줄이고 비용 절감 가능

 

실습

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering

from sklearn.metrics import silhouette_score
from sklearn.decomposition import PCA

# 1. Wine 데이터셋 불러오기
from sklearn.datasets import load_wine
wine = load_wine()
X = wine.data
y = wine.target  # 실제 레이블(군집 평가엔 직접 사용 안 함)

# k-means
kmeans = KMeans(n_clusters=3, random_state=42)
kmeans_labels = kmeans.fit_predict(X)

# # DBSCAN
# dbscan = DBSCAN(eps=0.5, min_samples=2)
# dbscan_labels = dbscan.fit_predict(X)

# 계층적 클러스터링
agg = AgglomerativeClustering(n_clusters=3)
agg_labels = agg.fit_predict(X)

kmeans_sil = silhouette_score(X, kmeans_labels)
# dbscsan_sil = silhouette_score(X, dbscan_labels)
agg_sil = silhouette_score(X, agg_labels)

print("K-means ➡️ 실루엣 점수:", kmeans_sil, " 클러스터 라벨:", np.unique(kmeans_labels))
# print("DBSCAN ➡️ 실루엣 점수:", dbscsan_sil, " 클러스터 라벨:", np.unique(dbscan_labels))
print("Agglomerative ➡️ 실루엣 점수:", agg_sil, " 클러스터 라벨:", np.unique(agg_labels))

# 시각화 위한 PCA로 차원 축소
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)

# 시각화
fig, axes = plt.subplots(1, 3, figsize=(15,4))

# K-means
axes[0].scatter(X_pca[:, 0], X_pca[:, 1], c=kmeans_labels)
axes[0].set_title("K-Means")

# DBSCAN
# axes[1].scatter(X_pca[:, 0], X_pca[:, 1], c=dbscan_labels)
# axes[1].set_title("DBSCAN")

# Agglomerative
axes[2].scatter(X_pca[:, 0], X_pca[:, 1], c=agg_labels)
axes[2].set_title("Agglomerative")

plt.tight_layout()
plt.show()

 

  • 군집 수 미리 어떻게 정하나: K-Means의 경우 엘보 기법이나 실루엣 계수를 활용해 여러 k 값 시도해보고, 각 경우의 군집 품질 지표를 비교해 적정 군집 수 결정
    • 엘보(elbow) 기법: 특정 범위의 k값 바꿔가면 모델 학습한 뒤, 각 k에 대한 군집 내 제곱 오차 합(SSE) 또는 WCSS(Within-Cluster Sum of Squares) 값을 구해 그래프로 표현하고 어느 시점에서 꺾여 완만해지는 지점을 찾는 것
    • 그 elbow point 지점에서의 k 값을 결정하는 방식

 

  • k-means와 DBSCAN 결정 경우
    • 데이터의 구조와 필요에 따라 다름
      • 군집 수를 알고 있거나 대략적인 예상이 가능하다면 K-Means가 간다하고 빠름
      • 군집이 구형 형태가 아닐 수 있거나 노이즈 처리가 중요한 경우 DBSCAN이 유리

 

  • 군집화 결과가 좋지 않을 경우 해볼 수 있는 것
    • 다른 군집화 알고리즘(GMM 등) 시도
    • 파라미터를 조정
    • 추가 변수를 고려해 새로운 피처 생성