๐ค ๋ฐ์ดํฐ ์ ์จ์ ๊ทธ๋ฃน์ ์ฐพ์๋ด๋ K-ํ๊ท ์๊ณ ๋ฆฌ์ฆ
์ค๋์ ๋น์ง๋ ํ์ต์ ๋ํ์ ์ธ ๊ตฐ์งํ ์๊ณ ๋ฆฌ์ฆ, K-ํ๊ท (K-Means) ์ ๋ํด ๊น์ด ํ๊ณ ๋ค์๋ค. ๋ง์น ์ ๋ฆฌ๋์ง ์์ ๊ฑฐ๋ํ ๋์๊ด์์ ๋น์ทํ ์ฃผ์ ์ ์ฑ ๋ค์ ์ฐพ์ ์๊ฐ๋ฅผ ์ ๋ฆฌํ๋ ์ฌ์์ฒ๋ผ, K-ํ๊ท ์ ๋ฐ์ดํฐ์ ์จ๊ฒจ์ง ๊ตฌ์กฐ๋ฅผ ์ฐพ์ ๊ทธ๋ฃน์ผ๋ก ๋ฌถ์ด์ฃผ๋ ๋ฉ์ง ์ญํ ์ ํ๋ค.
โจ โ๋ฐ์ดํฐ์ ์น๊ตฌ๋ค์ ์ฐพ์์ฃผ์!โ
K-ํ๊ท ์ ์ฌ์ฉํ๋ฉด ์ ๋ต์ด ์๋ ๋ฐ์ดํฐ ์์์๋ ์๋ฏธ ์๋ ํจํด๊ณผ ๊ทธ๋ฃน์ ๋ฐ๊ฒฌํ ์ ์๋ค.
๐ ๏ธ K-ํ๊ท (K-Means) vs. K-์ต๊ทผ์ ์ด์(K-NN)
์ด๋ฆ์ด ๋น์ทํด์ ํท๊ฐ๋ฆด ์ ์์ง๋ง, ๋ ์๊ณ ๋ฆฌ์ฆ์ ์์ ํ ๋ค๋ฅธ ๋ชฉํ๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
๊ตฌ๋ถ | K-ํ๊ท (K-Means) | K-์ต๊ทผ์ ์ด์ (K-NN) |
---|---|---|
ํ์ต ๋ฐฉ์ | ๋น์ง๋ํ์ต (Clustering) | ์ง๋ํ์ต (Classification) |
๋ชฉํ | ๋ ์ด๋ธ ์๋ ๋ฐ์ดํฐ๋ฅผ K๊ฐ์ ๊ตฐ์ง์ผ๋ก ๋๋ | ์ ๋ฐ์ดํฐ์ ํด๋์ค๋ฅผ K๊ฐ์ ์ด์์ ํตํด ๊ฒฐ์ |
๊ณตํต์ | K๊ฐ์ ์ ์ ์ง์ ํ๊ณ , ๊ฑฐ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋์ | ย |
โ๏ธ K-ํ๊ท ์ ์ด๋ป๊ฒ ๋์ํ ๊น?
K-ํ๊ท ์ ์ค์ฌ์ (Centroid)์ด๋ผ๋ ํน๋ณํ ์ ์ ๊ณ์ ์ด๋์ํค๋ฉด์ ์ต์ ์ ๊ตฐ์ง์ ์ฐพ์๋ธ๋ค.
- ์ด๊ธฐํ: K๊ฐ์ ์ค์ฌ์ ์ ์์์ ์์น์ ๋ฐฐ์นํ๋ค.
- ๊ตฐ์ง ํ ๋น: ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ฅ ๊ฐ๊น์ด ์ค์ฌ์ ์ ํ ๋นํ๋ค.
- ์ค์ฌ์ ์ ๋ฐ์ดํธ: ๊ฐ ๊ตฐ์ง์ ์ค์ฌ์ผ๋ก ์ค์ฌ์ ์ ์ด๋์ํจ๋ค.
- ๋ฐ๋ณต: ์ค์ฌ์ ์ด ๋ ์ด์ ์์ง์ด์ง ์์ ๋๊น์ง 2, 3๋ฒ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ฉด, ๋ง์นจ๋ด ์ต์ ์ ๊ตฐ์ง์ด ํ์ํ๋ค! ๐
๐ Scikit-learn์ผ๋ก K-ํ๊ท ๊ตฌํํ๊ธฐ
๋ถ๊ฝ(Iris) ๋ฐ์ดํฐ์ ์ผ๋ก ์ง์ K-ํ๊ท ๊ตฐ์งํ๋ฅผ ์ค์ตํด๋ดค๋ค.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
# 1. ๋ฐ์ดํฐ ๋ก๋
iris = load_iris()
irisDF = pd.DataFrame(iris.data, columns=iris.feature_names)
# 2. K-ํ๊ท ๋ชจ๋ธ ํ์ต (K=3)
kmeans = KMeans(n_clusters=3, random_state=121)
kmeans.fit(irisDF)
# 3. ๊ตฐ์ง ๊ฒฐ๊ณผ ํ์ธ
print(kmeans.labels_)
# [1 1 1 ... 0 0 0]
inertia_
์์ฑ์ ํด๋ฌ์คํฐ ๋ด ๋ฐ์ดํฐ๋ค์ด ์ผ๋ง๋ ์ ๋ญ์ณ์๋์ง๋ฅผ ๋ํ๋ด๋๋ฐ, K๊ฐ ์ปค์ง์๋ก ๋ฌด์กฐ๊ฑด ์์์ ธ์ ์ต์ ์ K๋ฅผ ํ๋จํ๋ ์ ๋์ ์ธ ๊ธฐ์ค์ด ๋๊ธฐ๋ ์ด๋ ต๋ค. ๐ค
์ต์ ์ K ์ฐพ๊ธฐ: ์๋ณด์ฐ(Elbow) ๊ธฐ๋ฒ
๊ทธ๋ ๋ค๋ฉด ์ต์ ์ K๋ ์ด๋ป๊ฒ ์ฐพ์๊น? ๋ฐ๋ก ์๋ณด์ฐ ๊ธฐ๋ฒ์ ์ฌ์ฉํ๋ค. K๋ฅผ ๋๋ ค๊ฐ๋ฉฐ inertia
๊ฐ์ ๋ณํ๋ฅผ ๊ทธ๋ํ๋ก ๊ทธ๋ ธ์ ๋, ํ๊ฟ์น์ฒ๋ผ ๊ธ๊ฒฉํ ๊บพ์ด๋ ์ง์ ์ด ๋ฐ๋ก ์ต์ ์ K๊ฐ ๋๋ค.
# ์๋ณด์ฐ ๊ธฐ๋ฒ์ผ๋ก ์ต์ ์ K ์ฐพ๊ธฐ
inertias = []
K_range = range(1, 12)
for k in K_range:
km = KMeans(n_clusters=k, random_state=121)
km.fit(iris.data)
inertias.append(km.inertia_)
# ๊ทธ๋ํ ์๊ฐํ
plt.plot(K_range, inertias, '-o')
plt.xlabel('Number of clusters, K')
plt.ylabel('Inertia')
plt.show()
๊ทธ๋ํ๋ฅผ ๋ณด๋ 3์์ ๊ธฐ์ธ๊ธฐ๊ฐ ์๋งํด์ง๋ ๊ฒ์ ํ์ธํ๋ค.
๐ K-ํ๊ท ์ ์ฅ์ ๊ณผ ๋จ์ ๐
์ฅ์ | ๋จ์ |
---|---|
์ดํด์ ๊ตฌํ์ด ์ฝ๊ณ ์ง๊ด์ ์ด๋ค. | K๊ฐ์ ์ง์ ์ค์ ํด์ผ ํ๋ค. ๐ญ |
์๋ ด์ด ๋ณด์ฅ๋๋ค. | ๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ์ด๋ผ ์ฐจ์์ด ๋ง์์ง๋ฉด ๋ณต์ก๋๊ฐ ์ฆ๊ฐํ๋ค. |
๋์ฉ๋ ๋ฐ์ดํฐ์๋ ์ ์ฉ ๊ฐ๋ฅํ๋ค. | ์ด์์น(Outlier)์ ์ค์ผ์ผ์ ๋ฏผ๊ฐํ๋ค. |
- | ์ด๊ธฐ ์ค์ฌ์ ์์น์ ๋ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ ๋ฌ๋ผ์ง ์ ์๋ค. |
๐ ์ฑ๋ฅ ํฅ์์ ์ํ ๊ธฐ๋ฒ๋ค
K-ํ๊ท ์ ๋จ์ ์ ๋ณด์ํ๊ณ ์ฑ๋ฅ์ ๋์ด์ฌ๋ฆฌ๊ธฐ ์ํ ๋ฐฉ๋ฒ๋ค๋ ์ ์ฉํด๋ดค๋ค.
- PCA (์ฐจ์ ์ถ์): ๊ณ ์ฐจ์ ๋ฐ์ดํฐ์ ๊ณ์ฐ ๋ณต์ก๋๋ฅผ ์ค์ฌ์ฃผ์๋ค.
- ์ค์ผ์ผ๋ง (Scaling):
StandardScaler
๋ก ํผ์ฒ ์ค์ผ์ผ์ ๋ง์ถ๋ ์ด์์น์ ๋ํ ๋ฏผ๊ฐ๋๋ฅผ ์ค์ผ ์ ์์๋ค.
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
# ์ค์ผ์ผ๋ง
scaler = StandardScaler()
X_scaled = scaler.fit_transform(iris.data)
# PCA๋ก 2์ฐจ์์ผ๋ก ์ถ์
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
# K-Means ๋ค์ ํ์ต
kmeans_pca = KMeans(n_clusters=3, random_state=121)
kmeans_pca.fit(X_pca)
๐ ๊ตฐ์งํ, ์ผ๋ง๋ ์ ๋์๊น? (์ฑ๋ฅ ํ๊ฐ)
1. ์ค๋ฃจ์ฃ ๊ณ์ (Silhouette Coefficient)
- ์ ๋ต ๋ ์ด๋ธ์ด ์์ ๋ ์ฌ์ฉํ๋ ์งํ๋ค.
- ๊ตฐ์ง ๋ด ๋ฐ์ดํฐ๋ ์ผ๋ง๋ ๊ฐ๊น๊ณ , ๋ค๋ฅธ ๊ตฐ์ง๊ณผ๋ ์ผ๋ง๋ ๋ฉ๋ฆฌ ๋จ์ด์ ธ ์๋์ง๋ฅผ ์ธก์ ํ๋ค.
- 1์ ๊ฐ๊น์ธ์๋ก ์ข์ ๊ตฐ์งํ๋ก ํ๋จํ๋ค.
from sklearn.metrics import silhouette_score
score = silhouette_score(iris.data, kmeans.labels_)
print('์ค๋ฃจ์ฃ ์ ์: {0:.3f}'.format(score))
# ์ค๋ฃจ์ฃ ์ ์: 0.553
2. Homogeneity, Completeness, V-measure
- ์ ๋ต ๋ ์ด๋ธ์ด ์์ ๋ ์ฌ์ฉํ๋ค.
- Homogeneity (๊ท ์ง์ฑ): ๊ฐ ๊ตฐ์ง์ด ๋์ผํ ์ค์ ํด๋์ค๋ก๋ง ๊ตฌ์ฑ๋ ์ ๋.
- Completeness (์์ ์ฑ): ์ค์ ํด๋์ค์ ๋ฐ์ดํฐ๋ค์ด ๋ชจ๋ ๋์ผํ ๊ตฐ์ง์ ์ํ ์ ๋.
- V-measure: ์ ๋ ๊ฐ์ ์กฐํ ํ๊ท ์ด๋ค.
from sklearn.metrics import homogeneity_score, completeness_score, v_measure_score
print("๊ท ์ง์ฑ:", homogeneity_score(iris.target, kmeans.labels_))
print("์์ ์ฑ:", completeness_score(iris.target, kmeans.labels_))
print("V-measure:", v_measure_score(iris.target, kmeans.labels_))
๐ง K-ํ๊ท ์ ๋์: ๋ฐ๋ ๊ธฐ๋ฐ ํด๋ฌ์คํฐ๋ง (DBSCAN)
K-ํ๊ท ์ ์ํ ๊ตฐ์ง์ ๊ฐํ์ง๋ง, ๋ณต์กํ ๋ชจ์์ ๊ตฐ์ง์ ์ ์ฐพ์๋ด์ง ๋ชปํ๋ค. ์ด๋ด ๋ DBSCAN์ ์ฌ์ฉํ ์ ์๋ค.
- ๋ฐ์ดํฐ๊ฐ ๋ฐ์ง๋ ์ง์ญ์ ์ฐพ์ ๊ตฐ์งํํ๋ ๋ฐฉ์์ด๋ค.
- K-ํ๊ท ๊ณผ ๋ฌ๋ฆฌ ํด๋ฌ์คํฐ ๊ฐ์๋ฅผ ๋ฏธ๋ฆฌ ์ ํ ํ์๊ฐ ์๊ณ , ๋ ธ์ด์ฆ(์ด์์น)๋ฅผ ์๋์ผ๋ก ๋ถ๋ฅํด์ค์ ํธ๋ฆฌํ๋ค.
from sklearn.cluster import DBSCAN
dbscan = DBSCAN(eps=0.6, min_samples=8)
dbscan_labels = dbscan.fit_predict(iris.data)
# -1์ ๋
ธ์ด์ฆ(์ด์์น)๋ก ๋ถ๋ฅ๋ ๋ฐ์ดํฐ
print(np.unique(dbscan_labels, return_counts=True))
โจ ์ค๋์ ํ๊ณ
K-ํ๊ท ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ๋จํ๋ฉด์๋ ๊ฐ๋ ฅํ ๊ตฐ์งํ ๊ธฐ๋ฒ์ด์๋ค. ํนํ ์๋ณด์ฐ ๊ธฐ๋ฒ์ผ๋ก ์ต์ ์ K๋ฅผ ์ฐพ์๋ด๋ ๊ณผ์ ์ด ํฅ๋ฏธ๋ก์ ๋ค. ํ์ง๋ง K๊ฐ์ ์ง์ ์ ํด์ผ ํ๊ณ , ์ด์์น์ ๋ฏผ๊ฐํ๋ค๋ ๋จ์ ๋ ๋ช ํํ ์๊ฒ ๋์๋ค.
๋ค์์๋ ์ค๋ ๋ฐฐ์ด DBSCAN์ฒ๋ผ ๋ฐ๋ ๊ธฐ๋ฐ ํด๋ฌ์คํฐ๋ง์ด๋ ๋ค๋ฅธ ๊ตฐ์งํ ์๊ณ ๋ฆฌ์ฆ์ ๋ ๊น์ด ํ๊ณ ๋ค์ด, ๋ฐ์ดํฐ์ ํน์ฑ์ ๋ง๋ ์ต์ ์ ๋ฐฉ๋ฒ์ ์ ํํ๋ ๋ฅ๋ ฅ์ ๊ธธ๋ฌ์ผ๊ฒ ๋ค. ๐