728x90
Clustering 기법을 사용하여 비지도 학습을 해 보자.
지도 학습보다 정확도는 떨어질 수 있다. 라벨링이 되어 있지 않을 때, 전체적인 트렌드를 보거나, 데이터가 너무 많을 때 사용한다. 웬만하면 라벨링을 해서 지도 학습을 하는 게 좋다.

 

비지도 학습의 대표적인 기법은 바로 Clustering 기법이다.

  • Clustering Algorythm
    • K-평균 군집화(K-Means Clustering)
    • 계층적 군집화(Hierarchical Clustering)

  • K-평균 군집화(K-Means Clustering)
    • Step1. 각 데이터 포인트에서 가장 가까운 중심점을 찾아 그 중심점에 해당하는 클러스터로 할당한다.
    • Step2. 할당된 클러스터 기반으로 새로운 중심점을 계산한다. 중심점 = 클러스터 내부 점들 좌표의 산술 평균.
    • Step3. 각 클러스터의 할당이 바뀌지 않을 때까지 반복한다.

     ■ 점과 점 사이의 거리 측정 방법

  • Manhattan Distance - 수직 이동 거리 측정

x가 (1, 1)이고 y가 (3, 3)일 때, D(x,y) = |3-1| + |3-1| = 4

 

  • Euclidean Distance - 점과 점 사이의 최단 거리 측정

x가 (1, 1)이고 y가 (3, 3)일 때, D(x, y) = {(3-1)^2 + (3-1)^2}의 제곱근 = √8

 

# 와인 데이터를 가지고 실습해 보자.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sklearn
import warnings
warnings.filterwarnings('ignore')

# 와인 데이터 가져오기
from sklearn.datasets import load_wine
wine = load_wine()
print(wine.DESCR)
>>

.

.

.

# 변수에 저장하기
data = wine.data
label = wine.target
columns = wine.feature_names

# Dataframe 객체로 만들기
data = pd.DataFrame(data, columns=columns)

# 헤드 정보를 확인해 보면,
data.head()

>>

※ Scikit-Learn의 K-Means 클래스는 기본적으로 유클리디안 거리를 사용하여 군집화를 수행한다.

# 데이터 전처리. K-Means를 사용하여 데이터 평준화 시키기
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
data = scaler.fit_transform(data)

# 데이터 크기 확인하기
print(data)
>> (178, 13)

# 13개 columns가 있는 데이터(13차원)가 178개 있다는 것. 데이터를 학습시킬 때 패턴 찾기가 잘 안 될 수 있다.
따라서 차원의 축소가 필요.

# PCA(차원의 축소) 몇 차원으로 줄일 것인지? n_components값을 준다. (2차원)
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
data = pca.fit_transform(data)
print(data)

 

데이터를 확인해 보면,
>>

.

.

.

# 준비된 데이터를 가지고 K-Means를 사용하여 학습시킨다.
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3) # --> low, middle, high로 3개로 분류

#학습하기. (data)를 준다.
kmeans.fit(data)

# 분류 작업하기 전 예측하기
cluster = kmeans.predict(data)

# cluster값 확인해 보기. Numpy배열
print(cluster)
 
>>

분류가 되었다.

 

# 데이터 시각화하기

plt.scatter(data[:,0],data[:,1], c=cluster,
            edgecolor='black',linewidth=1)
 
*x값은 데이터에서 0번 항목, y값은 1번 항목
*color값을 cluster로 주면, cluster에 따라 색이 분류된다.
 
>>

  • Hierrarchical Clustering
    • 거리나 유사도를 기반으로 클러스터를 형성하는 알고리즘
    • Step1. 각 데이터 포인트를 클러스터로 할당한다. n개의 클러스터
    • Step2. 가까운 클러스터끼리 병합한다.
    • Step3. 1개의 클러스터가 될 때까지 반복한다.

     ■ 가장 가까운 클러스터를 어떻게 찾을 수 있을까?

  • Single Linkage: 두 클러스터 내의 가장 가까운 점 사이의 거리

  • Complete Linkage: 두 클러스터 내의 가장 먼 점 사이의 거리

  • Average Linkage: 두 클러스터 내의 모든 점 사이의 평균 거리

■ 준비된 데이터를 가지고 Hierarchical Clustering을 사용하여 학습시킨다.

 

from sklearn.cluster import AgglomerativeClustering

single_clustering = AgglomerativeClustering(n_clusters=3,linkage='single')
complete_clustering = AgglomerativeClustering(n_clusters=3,linkage='complete')
average_clustering = AgglomerativeClustering(n_clusters=3,linkage='average')

# single, complete, average 세 가지 속성을 만든다.
# 학습하기
single_clustering.fit(data)
complete_clustering.fit(data)
average_clustering.fit(data)

# 변수에 저장하기
single_cluster = single_clustering.labels_
complete_cluster = complete_clustering.labels_
average_cluster = average_clustering.labels_

 

*출력해 보면,

 
--> 결과를 보니,  single은 제대로 분류X, complete로 된 것은 웬만큼 분류O, average는 잘 된 듯하다. 즉 complete나 average로 보는 것이 좋겠다는 결론을 내릴 수 있다.
 
 
 
# 시각화하기. x, y 좌표 주기
plt.scatter(data[:,0],data[:,1],c=single_cluster)
>>
 
plt.scatter(data[:,0],data[:,1],c=complete_cluster)
>>
plt.scatter(data[:,0],data[:,1],c=average_cluster)
>>

      --> Good!                                

 

plt.scatter(data[:,0],data[:,1],c=label)
>>
--> 이건 실제 데이터. average cluster와 매우 유사하다. 
 
 
*dendrogram을 이용해서 확인해 보자.
*figsize=그림판 사이즈
*노드 숫자2, children.shape[0]+2)
 
from scipy.cluster.hierarchy import dendrogram
plt.figure(figsize=(10,10))
children = single_clustering.children_
distance = np.arange(children.shape[0])
no_of_observations = np.arange(2, children.shape[0]+2)
linkage_matrix = np.column_stack([children, distance, no_of_observations]).astype(float)
 
---> 여기까지 dendrogram을 그리기 위한 준비 과정이다.

dendrogram(linkage_matrix, p=len(data), labels=single_cluster,
           show_contracted=True, no_labels=True)
 
*show_contracted 선들을 연결되게 할 것인지.
 
>>

 

.

.

.

 
 
 

 생각보다 구분이 잘 X

이번엔 Silhoutte으로 확인해 보자.

실루엣 값은 클러스터 안의 데이터들이 다른 클러스터와 얼마나 비슷한가를 나타낸다. 같은 클러스터 내 점들의 거리는 가깝고, 서로 다른 클러스터 간의 거리가 멀수록 높은 값이 나온다.

*비지도 학습이므로 X_train, y_train 값이 아닌 data만 준다.

 ---> cluster = kmeans.predict(data)

---> best_score는 1이 가장 좋은 값이므로 우선 -1로 준다.

from sklearn.metrics import silhouette_score

best_n = 1
best_score = -1

for n_cluster in range(2,11):
  kmeans = KMeans(n_clusters=n_cluster)
  kmeans.fit(data)
  cluster = kmeans.predict(data)
  score = silhouette_score(data, cluster)

  print('클러스터의 수: {} 실루엣 점수:{:.2f}'.format(n_cluster, score))

  if score > best_score:
    best_n = n_cluster
    best_score = score

print('가장 높은 실루엣 점수를 가진 클러스터 수: {}, 실루엣 점수 {:.2f}'.format(best_n, best_score))

>>

 
from sklearn.metrics import silhouette_score

best_n = 1
best_score = -1

for n_cluster in range(2,11):
  average_clustering = AgglomerativeClustering(n_clusters=n_cluster,linkage='average')
  average_clustering.fit(data)
  cluster = average_clustering.labels_
  score = silhouette_score(data, cluster)

  print('클러스터의 수: {} 실루엣 점수:{:.2f}'.format(n_cluster, score))

  if score > best_score:
    best_n = n_cluster
    best_score = score

print('가장 높은 실루엣 점수를 가진 클러스터 수: {}, 실루엣 점수 {:.2f}'.format(best_n, best_score))
 
>>

 

모델 저장하기. 확장자*.pkl

 

지금 배우는 부분은 극히 일부!

앞으로 더 힘차게 달려보자~

728x90

+ Recent posts