가장 고전적이고 직관적인 군집화 기법
1. 임의의 중심점 설정
임의의 장소에 사전에 설정해준 군집의 수만큼의 중심점을 배치해준다. 데이터를 잘 구분하기 위해서는 중심이 데이터들의 가운데에 있어야한다.
2. 평균의 중심으로 중심점 이동
각 데이터와 중심점 간의 거리를 계산하여 거리가 평균적으로 비슷할 때까지 중심점을 이동시킨다.
3. 중심점 확정 및 최종 군집화
위 방법을 계속 반복하여 더 이상 중심점이 움직이지 않는 순간이 오도록 한다.
*K-means알고리즘은 데이터간의 거리로 군집화를 진행하기 떄문에 멀리 떨어져있는 데이터에 관해서는 취약하다.
#군집화용 데이터를 생성하고 산점도를 그려본다.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=500,
n_features=2,
centers=3,
cluster_std=2,
random_state=42)
df = pd.DataFrame(data=X, columns = ["x1", "x2"])
df['label'] = y
target_list = np.unique(y)
color_lst = ['r', 'g', 'b']
for target, color in zip(target_list, color_lst) :
target_cl = df[df['label']==target]
plt.scatter(x=target_cl['x1'], y = target_cl['x2'], edgecolor = 'k', color = color)
plt.show()
#군집화 진행
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3, random_state = 42) #KMeans알고리즘 실행 코드
kmeans.fit(X)
cluster_labels = kmeans.labels_
df['clusters'] = cluster_labels
centers = kmeans.cluster_centers_
unique_labels = np.unique(cluster_labels)
markers=['o', 's', '^', 'P','D','H','x']
for label in unique_labels:
label_cluster = df[df['clusters']==label]
center_x_y = centers[label]
plt.scatter(x=label_cluster['x1'], y=label_cluster['x2'], edgecolor='k',
marker=markers[label] )
plt.scatter(x=center_x_y[0], y=center_x_y[1], s=200, color='white',
alpha=0.9, edgecolor='k', marker=markers[label])
plt.scatter(x=center_x_y[0], y=center_x_y[1], s=70, color='k', edgecolor='k',
marker='$%d$' % label)
plt.show()
print()
print("👀실제 값과 군집 비교👀")
print(df.groupby('label')['clusters'].value_counts())
군집이 잘 형성되었는지 확인하는 지표
실루엣 계수 : 군집 내의 데이터끼리 얼마나 잘 뭉쳐있는지, 다른 군집의 데이터와는 얼마나 멀리 떨어져 있는지 측정하는 지표. -1~1 사이의 값을 가진다. (-1일수록 좋지 않음)
from sklearn.metrics import silhouette_score, silhouette_samples
## 각 데이터별 실루엣 점수
samples = silhouette_samples(X.data, df['clusters']) #silhouette_samples
df['silhouette'] = samples
## 전체 실루엣 점수
score = silhouette_score(X.data, df['clusters']) #silhouette_score
print(f"🚀전체 실루엣 점수🚀\n{score:.2f}\n")
print("📃군집별 평균 실루엣 점수📃")
print(df.groupby('clusters')['silhouette'].mean())
<KMeans 외에 다른 군집화 기법>
DBSCAN(밀도 기반 클러스터링): 밀도가 높은 부분을 클러스터링 하는 방식
GMM(가우시안 혼합 모델): Gaussian 분포가 여러 개 혼합된 클러스터링 알고리즘
계층적 군집화 : 여러개의 군집 중에서 가장 유사도가 높은 군집 두개를 선택하여 하나로 합치는 것
데이터를 묘사하는 Feature가 너무 많으면 혼란을 초래하기 때문에 효율적으로 줄여야할 필요가 있다.
1. Feature Selection : 말그대로 필요한 Feature만 선택
2. Feature Extraction : 기존의 Feature를 살짝 변형하여 압축. 대표기법 PCA(공분산, 고유벡터, 고유값 개념 필요)
#PCA 기법 사용
import pandas as pd
import numpy as np
from sklearn.datasets import *
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
X, y = load_iris(return_X_y=True, as_frame=True)
normal_dataset = pd.concat([X, y], axis=1)
ss = StandardScaler()
scaled_X = ss.fit_transform(X)
pca = PCA(n_components=2) #PCA 코드
pca_features = pca.fit_transform(scaled_X) #fit_transform
pca_col_lst = [f"pca_{i}" for i in range(1, pca_features.shape[1]+1)]
pca_dataset = pd.DataFrame(pca_features, columns=pca_col_lst)
pca_dataset = pd.concat([pca_dataset, y], axis=1)
print("🚩압축된 각 축이 전체 변수를 얼마나 설명하는지🚩")
print(pca.explained_variance_ratio_, f"-> 전체 설명률 : {sum(pca.explained_variance_ratio_)*100:.2f}%")
pca_dataset
압축된 변수들로 학습시킨 모델의 성능 차이 비교(분류모델은 RandomForest)
from sklearn.metrics import classification_report
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
## normal dataset
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
rf_clf = RandomForestClassifier(random_state = 42)
rf_clf.fit(X_train, y_train)
preds= rf_clf.predict(X_val)
print("🤖일반 데이터셋 성능🤖")
print(classification_report(y_val, preds))
## PCA datset
pca_X_tr, pca_X_val, pca_y_tr, pca_y_val = train_test_split(pca_features, y, test_size=0.2, random_state=42)
rf_clf = RandomForestClassifier(random_state = 42)
rf_clf.fit(pca_X_tr, pca_y_tr)
pca_preds= rf_clf.predict(pca_X_val)
print("🤖PCA 데이터셋 성능🤖")
print(classification_report(pca_y_val, pca_preds))
Loading : 원본 변수가 각 PCA축에 기여하는 정도
loadings = pd.DataFrame(pca.components_.T, columns=pca_col_lst,index=X.columns)
loadings.sort_values(by="pca_1", ascending=False)
보통 절대값이 클 수록, 해당 변수가 축을 만들 때 많이 기여했다고 해석한다.
petal length이 pca_1에 많이 기여했고, sepal width가 pca_2에 많은 기여를 했다.
정보 감사합니다.