AI/Machine Learning

[Machine Learning] 비지도 학습 (Unsupervised Learning)

byunghyun23 2023. 6. 2. 02:23

비지도 학습(unsupervised learning)은 라벨링이 되어 있지 않은 데이터를 이용하는 학습 방법입니다.

즉, 타겟 데이터 없이 피처(feature) 데이터만을 이용하여 모델을 학습시킵니다.

지도 학습(supervised learning)에서 데이터 분류를 말 그대로 분류라고 했지만, 비지도 학습에서 분류는 군집(clustering)이라고 부릅니다. 보통 군집보다는 클러스터링이란 단어로 많이 사용합니다.

 

클러스터링에는 여러 방법이 있지만 K-평균 클러스터링(K-means clustering)만 알아보도록 하겠습니다.

K-평균 클러스터링은 N개의 데이터를 K개의 클러스터로 나누는 방법입니다.

자세히 말하면, 각 데이터 포인트와 각 그룹 평균 간의 거리를 계산한 후 가장 가까운 클러스터로 배정하는 방법입니다.

여기서 각 클러스터의 평균은 해당 그룹에 속하는 데이터 포인트의 평균값을 구함으로써 계산할 수 있습니다.

 

데이터를 K-평균 클러스터링을 적용해 나누기 위해 각 그룹의 평균까지의 거리를 계산하는데, 여기서 거리 계산은 유클리드 거리(euclidean distance)를 사용합니다.

데이터 포인트 x, y 사이의 유클리드 거리 공식은 아래와 같습니다.

 

K-평균 클러스터링 알고리즘 단계는 다음과 같습니다.

1. 그룹 평균 초기화

먼저 각 그룹의 평균을 랜덤값으로 초기화합니다.

2. 그룹 할당

유클리드 거리를 이용하여 각 데이터 포인트를 가장 가까운 그룹 평균에 해당하는 그룹에 할당합니다.

3. 평균 업데이트

모든 데이터 포인트가 그룹에 속해지면,  각 그룹에 대한 새로운 평균값을 계산합니다. (그룹에 속한 데이터 평균)

4. 반복

2단계에서 그룹 내 데이터가 변하지 않을 때까지 2, 3단계를 반복합니다.

 

아래는 K-평균 클러스터링 컨버전스입니다.

ref: https://commons.wikimedia.org/wiki/File:K-means_convergence.gif

 

K-평균 클러스터링은 사용하기 쉽지만, 가중치가 없기 때문에 그룹 간 데이터의 밀도 차이가 있을 경우 클러스터링이 잘 되지 않는 단점이 있습니다. 또한 그룹 모양을 고려하지 않고, K의 값을 프로그래머가 직접 지정해야 합니다.

 

실습은 sklearn KMeans를 사용해 보겠습니다.

from sklearn.datasets import make_blobs

import pandas as pd
import matplotlib.pyplot as plt

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score


# 데이터 생성
X, y = make_blobs(n_samples=100,
                 n_features=2,
                 centers=5,
                 random_state=10)

# 생성된 데이터 차원 확인
print(X.shape)
print(y.shape)

# 라벨링 되지 않은 데이터 플랏
plt.scatter(X[:, 0], X[:, 1],
            c='gray',
            edgecolor='black',
            marker='o')
plt.show()

# k-means clustering
kmc = KMeans(n_clusters=5,
             init='random',
             max_iter=100,
             random_state=0)
kmc.fit(X)
label_kmc = kmc.labels_
print(label_kmc)

# 시각화를 위한 데이터프레임 생성
kmc_columns = ['kmc_comp1', 'kmc_comp2']
X_kmc_df = pd.DataFrame(X, columns=kmc_columns)
X_kmc_df['target'] = y
X_kmc_df['label_kmc'] = label_kmc
print(X_kmc_df.head(5))

# 타겟 클래스 종류 확인
print(set(X_kmc_df['target']))
print(set(X_kmc_df['label_kmc']))

# k-means clustering을 이용한 데이터 플랏
df = X_kmc_df
markers=['o', 'x', '^', 's', '*']

for i, mark in enumerate(markers):
    df_i = df[df['label_kmc'] == i]
    target_i = i
    X1 = df_i['kmc_comp1']
    X2 = df_i['kmc_comp2']
    plt.scatter(X1, X2,
                marker=mark,
                label=target_i)

plt.xlabel('kmc_component1')
plt.ylabel('kmc_component2')
plt.legend()
plt.show()

# 실제 타겟 플랏
df = X_kmc_df
markers=['o','x','^','s','*']

for i, mark in enumerate(markers):
    df_i = df[df['target'] == i]
    target_i = i
    X1 = df_i['kmc_comp1']
    X2 = df_i['kmc_comp2']
    plt.scatter(X1, X2,
                marker=mark,
                label=target_i)

plt.xlabel('kmc_component1')
plt.ylabel('kmc_component2')
plt.legend()
plt.show()


# 모형 평가
sil_score = silhouette_score(X, label_kmc)
print(sil_score)

make_blobs()를 호출하여 랜덤으로 데이터를 생성합니다. 생성된 데이터의 shape는 (100, 2)이며 시각화하면 아래와 같습니다. 눈으로 봤을 때, 5개의 군집으로 구성되어 있습니다. 클러스터링이 잘 되는지 확인하기 위하여 K의 값을 5로 설정하여 학습을 진행합니다.

학습 종료 후 클러스터링을 어떻게 했는지 확인합니다.

label_kmc은 target과 같은 번호로 클러스터링 되지 않았지만(중요하지 않습니다),

시각화 해보면 잘 클러스터링 되었습니다.

마지막으로 실루엣 스코어(silhouette score)를 계산합니다.

실루엣 스코어는 -1에서 1사이의 값을 가지며, 1의 가까울수록 군집 간 거리가 멀다는 뜻(잘 클러스터링 되었음)입니다.

그리고 0에 가까울수록 근처 군집과 가까움을 의미하며, 0미만이면 다른 군집에 데이터가 할당되었다는 의미입니다.

위 데이터를 이용하여 K-평균 클러스터링 했을 때, 실루엣 스코어는 0.75를 얻었습니다.