[SK쉴더스 루키즈 24기] 머신러닝 기초(2) 비지도학습과 군집화

아굥·2024년 12월 24일
1

SK Shieldus Rookies

목록 보기
9/32

비지도학습 소개

1. 비지도학습의 정의와 활용 분야

정답(레이블)이 없는 데이터를 기반으로 학습하는 머신러닝의 한 방법

  • 입력 데이터에 포함된 숨겨진 패턴이나 데이터 구조를 파악하는데 초점을 맞춤
    ㄴ> 모델이 데이터를 보고 스스로 규칙을 발견하거나 데이터를 특정 기준에 따라 그룹으로 나눔

활용 분야

  • 군집화(Clustering): 데이터를 비슷한 특성을 가진 그룹으로 묶는 작업
  • 차원 축소(Demensionality Reduction): 데이터를 간결하고 유용한 형태로 변환
  • 이상치 탐지(Anomaly Detection): 정상 패턴을 벗어나는 데이터(이상치) 탐지
  • 추천 시스템(Recommendation System): 비슷한 데이터를 기반으로 사용자에게 추천을 제공

2. 비지도학습의 주요기법

  • 군집화(Clustering)
  • 차원 축소(Demensionality Reduction)
  • 이상치 탐지(Anomaly Detection)

군집화 기초

1. 군집화의 개념과 활용

주어진 데이터에서 유사한 특성을 가진 데이터 포인트들을 그룹으로 묶는 것

  • 각 그룹을 클러스터(Cluster)라고 함
  • 데이터는 사전에 분류 X, 살펴보며 그룹 형성

1) 주요 목표

  • 데이터 구조 파악: 데이터를 시각화 하거나 그룹화하여 숨겨진 패턴을 발견
  • 유사성 기반 그룹화: 데이터 포인트 간의 유사성을 기준으로 분류 -> 각 그룹이 내포하는 의미를 이해

2) 작동 방식

  • 유사성 측정: 데이터 포인트 간의 유사성을 측정하기 위해 거리 계산을 사용
  • 그룹화: 유사한 데이터 포인트들을 같은 그룹으로 묶음

3) 활용

  • 고객 세분화: 고객 데이터를 분석 -> 유사한 구매 패턴, 관심사, 행동을 가진 그룹으로 나눔
  • 이미지 세그멘테이션: 이미지의 픽셀을 비슷한 색상이나 질감을 가진 영역으로 나눔
  • 문서 분류 및 정보 검색: 문서를 주제별로 그룹화 -> 검색 및 추천 시스템에 활용
  • 이상치 탐지: 대부분의 데이터와 크게 다른 이상 데이터 감지
  • 추천 시스템: 유사한 관심사나 행동 패턴을 가진 사용자들을 그룹화 -> 추천 항목 생성

2. K-Means 알고리즘 원리와 적용

주어진 데이터를 K개의 클러스터로 나누는 비지도 학습 방법

  • 반복적이고 간단한 방식으로 데이터를 그룹화, 각 클러스터는 하나의 중심으로 설정

1) 활용

  • 고객 세분화: 고객 데이터를 K-Means로 클러스터링 -> 비슷한 소비 행동을 가진 그룹으로 분류
  • 이미지 압축: K-Means로 픽셀 생상을 클러스터링 -> 주요 색상만 유지
  • 문서 분류: 텍스트 데이터를 클러스터링 -> 문서를 주제별로 분류

2) 알고리즘 원리

① 초기 클러스터 중심(Centroid) 설정: 클러스터의 개수 K를 사용자가 미리 설정 -> 무작위나 데이터를 기반으로 선택
② 데이터 포인트 할당: 각 데이터 포인트를 가장 가까운 클러스터 중심에 할당 -> 가까운 중심에 속하는 데이터 포인트가 하나의 클러스터를 형성
③ 클러스터 중심 재계산: 각 클러스터에 속한 데이터 포인트들의 평균 위치를 계산 -> 새로운 클러스터 중심 설정
④ 반복: 위 과정을 반복 -> 클러스터 중심이 더 이상 변하지 않거나, 최대 반복 횟수에 도달하면 종료

3) 알고리즘 적용

① 데이터 준비: 군집화를 수행할 데이터 준비 및 정규화
② K값 선택: 원하는 클러스터 개수 K 결정
③ 알고리즘 실행: K-Means 알고리즘 적용하여 데이터 클러스터링
④ 결과 평가 및 시각화: 각 클러스터의 품질을 평가하고 시각적으로 확인


3. 클러스터 수(k) 선택 방법

K값 선택 방법

  • 엘보우 방법(Elbow Method): 여러 K값에 대해 K-Means 실행 -> 각 경우의 클러스터 내 데이터 거리 합(WCSS) 계산 -> K값에 따른 WCSS를 그래프로 그리고 기울기가 완화되는 지점에서 최적의 K 선택
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs

# 1. 데이터 생성
n_samples = 300                            
n_cluster = 3

x, y = make_blobs(n_samples=n_samples, centers=n_cluster, random_state=42, cluster_std=1.0)

# 2. 데이터 그래프 생성: 군집화 하기 전, 중앙값 구하기 전
plt.scatter(x[:, 0], x[:, 1], s=30, c='gray', label='original data')
plt.title('original data')
plt.xlabel('F1')
plt.ylabel('F2')
plt.show()

# 3. KMeans 객체 생성 학습
kmeans = KMeans(n_clusters=3, random_state=42)

# 4. 레이블 값 반환
cluster_labels = kmeans.fit_predict(x)

# 5. 군집 결과 시각화
plt.scatter(x[:, 0], x[:, 1], c=cluster_labels, cmap='viridis', s=30, label='cluster data')
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=200, c='red', marker='x')
plt.title('Clustering Data')
plt.xlabel('F1')
plt.ylabel('F2')
plt.show()

# 6. 최적의 K값 찾기
wcss = []
k_range = range(1, 10)

for k in k_range:
    kmeans_temp = KMeans(n_clusters=k, random_state=42)
    kmeans_temp.fit(x)
    wcss.append(kmeans_temp.inertia_)

plt.plot(k_range, wcss, marker='o')
plt.title('Elbow Method for Optimal K')
plt.xlabel('K')
plt.ylabel('WCSS')
plt.show()

군집화 응용 및 성능 평가

1. 클러스터링 결과의 해석

1) 결과 시각화

  • 클러스터링 결과를 해석하는 첫 단계는 데이터를 시각적으로 분석하는 것
  • 2D/3D 플롯데이터가 2차원이나 3차원으로 변환 가능하다면 각 클러스터를 색으로 구분하여 시각화
  • 클러스터의 중심 확인: 클러스터 내 데이터를 대표하는 점으로, 클러스터의 특성을 요약함

2) 특징 이해

  • 클러스터 내 데이터의 평균, 분포 확인: 주요 속성(특징)의 평균값과 분포를 분석함
    ㄴ> 각 클러스터의 특성을 이해할 수 있음
  • 클러스터 간의 차이점 파악: 클러스터를 서로 비교하여 공통점과 차이점을 확인

3) 적절성 평가

  • 데이터 응집도: 클러스터 내의 데이터가 얼마나 가까이 모여 있는지 -> 가까울수록 응집도 높음
  • 데이터 분리도: 다른 클러스터와 얼마나 잘 분리되어 있는지 -> 클러스터 간 거리가 멀수록 분리도 높음

4) 실질적 의미 부여

  • 도메인 지식을 활용한 해석: 클러스터링은 자동으로 클러스터를 나눔 -> 해석은 도메인 지식 필요
  • 이름 붙이기: 각 클러스터에 적절한 이름을 붙여줌

2. 클러스터 품질 평가

클러스터링 결과가 얼마나 잘 나왔는지 평가

1) 실루엣 점수

  • 데이터 포인트가 클러스터와 얼마나 잘 응집되어 있는지, 다른 클러스터와는 얼마나 잘 분리되어 있는지 나타냄
    ㄴ> 클러스터의 응집도와 분리도 동시에 평가 가능

  • 계산 공식 -> s(i) = b(i) - a(i) / max(a(i), b(i))
    a(i): 데이터 포인트 i와 같은 클러스터 내 다른 포인트 간 평균 거리 (응집도)
    b(i): 데이터 포인트 i와 가장 가까운 다른 클러스터 간 평균 거리 (분리도)
    s(i): 1이면 응집도/분리도 높음, 0이면 데이터 포인터가 경계에 가까움 (어느 클러스터에 속하는지 불확실), 음수면 잘못된 클러스터에 속했을 가능성 높음

  • 전체 실루엣 점수: 모든 데이터 포인트의 s(i) 값 평균

2) 실루엣 점수를 활용한 K값 선택

  • K-Mean의 가장 큰 과제 -> 적절한 클러스터 수 k를 선택하는 것

방법

  • 여러 k값에 대해 K-Means 실행
  • 각 k값에 대해 실루엣 점수 계산
  • 실루엣 점수 시각화
  • 실루엣 점수가 가장 높은 k값 선택
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from sklearn.metrics import silhouette_score, silhouette_samples

# 1. 데이터 생성
n_samples = 300                            
n_cluster = 3

x, y = make_blobs(n_samples=n_samples, centers=n_cluster, random_state=42, cluster_std=1.0)

# 2. 데이터 그래프 생성: 군집화 하기 전, 중앙값 구하기 전
plt.scatter(x[:, 0], x[:, 1], s=30, c='gray', label='original data')
plt.title('original data')
plt.xlabel('F1')
plt.ylabel('F2')
plt.show()

# 3. KMeans 객체 생성 학습
kmeans = KMeans(n_clusters=3, random_state=42)

# 4. 레이블 값 반환
cluster_labels = kmeans.fit_predict(x)

# 5. 군집 결과 시각화
plt.scatter(x[:, 0], x[:, 1], c=cluster_labels, cmap='viridis', s=30, label='cluster data')
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=200, c='red', marker='x')
plt.title('Clustering Data')
plt.xlabel('F1')
plt.ylabel('F2')
plt.show()

# 6. 실루엣 스코어
sil_avg = silhouette_score(x, cluster_labels)
print(sil_avg)

# 시각화를 위한 점수 계산
sil_value = silhouette_samples(x, cluster_labels)

y_lower = 10
for i in range(4):
    ith_cluster_sil_values = sil_value[cluster_labels == i]
    ith_cluster_sil_values.sort()
    size_cluster_i = ith_cluster_sil_values.shape[0]
    y_upper = y_lower + size_cluster_i

    # 막대그래프 추가
    plt.fill_betweenx(np.arange(y_lower, y_upper), 0, ith_cluster_sil_values)
    plt.text(-0.05, y_lower + 0.5*size_cluster_i, str(i))
    y_lower = y_upper + 10

plt.axvline(x=sil_avg, color='red', linestyle='--')
plt.title('silhouette plot')
plt.show()

3. 군집화 알고리즘 소개

1) 계층적 군집화(Hierarchical Clustering)

  • 데이터 포인트 간의 계층적 관계를 기반으로 클러스터를 형성 -> 데이터가 트리 형태로 그룹화됨

방법

  • 병합헙: 각 데이터 포인트를 개별 클러스터로 시작하여 가까운 클러스터를 병합
  • 분할형: 모든 데이터를 하나의 클러스터로 시작하여 점차 분리

장단점

  • 장점: 클러스터 수(k)를 미리 지정할 필요 X, 구조 시각적으로 확인 가능 (덴드로그램)
  • 단점: 큰 데이터셋에서는 계산 비용 높음, 클러스터 병합이나 분할이 초기에 잘못되면 결과에 영향 줌

작동 방식

① 각 데이터 포인트를 하나의 클러스터로 간주
② 두 클러스터 간 거리를 계산
③ 가장 가까운 두 클러스터를 병합
④ 클러스터가 하나가 될 때까지 반복

거리 계산 방법

  • 최단 연결법: 두 클러스터 간 가장 가까운 두 점 사이 거리
  • 최장 연결법: 두 클러스터 간 가장 먼 두 점 사이 거리
  • 평균 연결법: 두 클러스터 간 모든 점의 평균 거리
from sklearn.datasets import make_blobs
from scipy.cluster.hierarchy import dendrogram, linkage, fcluster
import matplotlib.pyplot as plt

# 1. 데이터 생성
data, _ = make_blobs(n_samples=200, centers=4, cluster_std=0.7, random_state=42)

# 2. 데이터 시각화 
plt.scatter(data[:, 0], data[:, 1], s=30, color='gray', label="Original Data")
plt.title("Generated Data")
plt.xlabel("F1")
plt.ylabel("F2")
plt.legend()

# 3. 계층적 군집화 적용
linked = linkage(data, method='ward')

# 4. 덴드로그램 시각화
plt.figure(figsize=(10, 7))
dendrogram(linked, truncate_mode='lastp', p=10, leaf_rotation=90, leaf_font_size=10)
plt.title("Hierarchical Clustering Dendrogram")
plt.xlabel("Cluster Size")
plt.ylabel("Distance")
plt.show()

# 4. 클러스터 형성
cluster_labels = fcluster(linked, t=7, criterion='distance')

# 5. 결과 시각화
plt.scatter(data[:, 0], data[:, 1], c=cluster_labels, cmap='rainbow', s=30)
plt.title("Hierarchical Clustering Results")
plt.xlabel("F1")
plt.ylabel("F2")
plt.show()

2) DBSCAN

  • 밀도를 기반으로 데이터 포인트를 클러스터링 -> 밀도가 낮은 데이터는 노이즈로 간주
    ㄴ> 데이터가 밀집된 영역을 클러스터로 정의
  • 클러스터 수(k) 미리 지정할 필요 X
  • 밀도가 낮은 데이터, 비구형 데이터 처리에 효과적, 이상치 검출에 강점
    ㄴ> 고차원 데이터에서는 거리 계산이 왜곡될 수 있음

매개변수

  • Epsilon(𝜖) = 포인트가 밀집되었다고 판단할 거리 임계값
  • MinPts = 한 포인트가 핵심 포인트가 되기 위한 최소 이웃 데이터 포인트 수

작동 방식

① 각 데이터 포인트에 대해 𝜖-이웃을 계산
② 𝜖-이웃 내 데이터 포인트 수가 MinPts 이상 -> 핵심(Core) 포인트로 간주
③ 핵심 포인트와 연결된 이웃 데이터는 같은 클러스터로 그룹화
④ 밀도가 낮은 포인트 -> 노이즈로 분류

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.cluster import DBSCAN

# 1. 데이터 생성
data, _ = make_moons(n_samples=300, noise=0.05, random_state=42)

# 2. 데이터 시각화
plt.scatter(data[:, 0], data[:, 1], s=30, color='gray', label="Original Data")
plt.title("Generated Data")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.legend()
plt.show()

# 3. DBSCAN 모델 생성 및 학습
dbscan = DBSCAN(eps=0.2, min_samples=5)

# 4. 데이터에 대한 클러스터 예측
cluster_labels = dbscan.fit_predict(data)

# 5. 클러스터링 결과 시각화
plt.scatter(data[:, 0], data[:, 1], c=cluster_labels, cmap='viridis', s=30)
plt.title("DBSCAN Clustering Results")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.colorbar(label="Cluster Label")
plt.show()

# 6. 클러스터링 결과 요약
unique_labels = set(cluster_labels)
print(f"Unique Clusters: {unique_labels}")

# 클러스터별 데이터 포인트 수 출력
for label in unique_labels:
    count = (cluster_labels == label).sum()
    if label == -1:
        print(f"Noise points: {count}")
    else:
        print(f"Cluster {label}: {count} points")
profile
열심히 살아보아요

0개의 댓글