카테고리 없음

AIOT - 붓꽃(iris) 데이터 군집화 예제

저선장 2023. 11. 21. 17:21

오늘은 붓꽃(iris) 데이터 군집화 예제를 다뤄보겠습니다.

 

예제 상세 내용은 아래와 같습니다.

1. 4개의 특성이 있지만, 차원 축소를 이용해 더 적은 수의 특성으로 학습을 시도할 것이다(PCA).
2. 더 적은 수의 특성으로 학습을 할 때는 군집화 모델을 사용하자(KMeans).
3. 군집화 학습을 마친 뒤에는 각 라벨에 대한 최적의 시각화 도구를 사용해 시각화를 하자(뭐가 좋을까?).

+ 붓꽃 데이터의 종류가 3가지(setosa, versicolor, virginica)임을 이미 알고있으니 클러스터는 3개로 사용해도 좋음

 

iris 데이터를 데이터프레임으로 가져오기

 

iris 데이터셋을 불러와 데이터프레임 형태로 저장합니다.

붓꽃의 종류(target)은 비지도 학습을 진행할것이므로 따로 저장하지 않습니다.

from sklearn.datasets import load_iris
import pandas as pd

iris = load_iris()
iris_df = pd.DataFrame(data=iris.data, columns=['sepal_length', 'sepal_width', 'petal_length', 'petal_width'])
iris_df.head()

 

PCA(차원축소) 적용

 

PCA를 사용해 차원(특성)을 축소합니다. iris 데이터의 특성은 4개이므로 그보다 작은 3으로 설정해줬습니다.

차원축소를 적용한 데이터는 iris_pca에 저장합니다.

 

explained_variance_ratio(설명된 분산의 비율)을 출력해보면 99%가 넘는 분산을 유지하고 있는 것을 알 수 있습니다.

 

적절한 주성분의 개수를 찾기 위해 explained_variance_ratio(설명된 분산의 비율) 그래프를 그려줍니다.

from sklearn.decomposition import PCA

pca = PCA(n_components=3) # 일단 컴포넨트는 3으로 설정
pca.fit(iris_df)
iris_pca = pca.transform(iris_df)

# 적정 컴포넨트(주성분의 개수) 찾기
import numpy as np
import matplotlib.pyplot as plt

print(np.sum(pca.explained_variance_ratio_)) # 설명된 분산(explained variance)의 비율

plt.plot(pca.explained_variance_ratio_)
plt.show() # 그래프가 급격히 꺾이는 부분이 적정 컴포넨트

주성분의 개수를 적절한 값으로 변경

pca = PCA(n_components=2)
pca.fit(iris_df)
iris_pca = pca.transform(iris_df)

print(np.sum(pca.explained_variance_ratio_))

그래프상 주성분 개수의 적정값은 1이지만 산점도 시각화를 위해 2로 설정

 

K-Means 모델 학습

 

군집화 모델중 K-Means를 통해 학습을 진행합니다.

클러스터의 적정 개수는 3개임을 알고 있으니 3으로 설정해줍니다.

from sklearn.cluster import KMeans
km = KMeans(n_clusters=3, random_state=42) # 클러스터 개수의 적정값은 3(iris의 종류)
km.fit(iris_pca)
print(np.unique(km.labels_, return_counts=True))

3개의 군집 각각 39, 50, 61개로 학습(정확도가 아쉽다.)

 

시각화

 

산점도 시각화를 진행합니다.

 

범례는 비지도 학습을 진행하였으므로 IRIS 1,2,3로 표기합니다.(x,y축도 마찬가지)

markers = ["o", "s", "*"] # 가독성을 위한 마커설정
for label in range(0, 3):
  data = iris_pca[km.labels_ == label]
  plt.scatter(data[:,0], data[:,1], marker=markers[label])
plt.legend(['IRIS 1', 'IRIS 2', 'IRIS 3'])
plt.xlabel('PCA 1')
plt.ylabel('PCA 2')
plt.show()

+ 주성분의 개수를 1로 변경하여 1차원 그래프로 나타내기

 

가장 적절한 주성분의 개수가 1이었지만 2차원 시각화 도구인 산점도로 나타내기 어려워 주성분을 2로 설정하였었는데요.

1차원 그래프로 나타내면 되지 않을까 해서 시본(Seaborn)의 실수 분포 플롯으로 나타내 보았습니다.

# 주성분의 개수를 적절한 값(1)로 변경
pca = PCA(n_components=1)
pca.fit(iris_df)
iris_pca = pca.transform(iris_df)

# KMeans 학습
from sklearn.cluster import KMeans
km = KMeans(n_clusters=3, random_state=42)
km.fit(iris_pca)

import seaborn as sns

for label in range(0, 3):
  data = iris_pca[km.labels_ == label]
  sns.rugplot(data[:,0])
plt.legend(['IRIS 1', 'IRIS 2', 'IRIS 3'])
plt.xlabel('PCA 1')
plt.show()

설명된 분산의 비율은 (당연하게도)줄었지만 학습결과는 동일하였습니다.

 

이렇듯 차원축소를 사용하면 데이터셋의 크기를 줄일 수 있고 차원(특성)수가 줄어들어 시각화하기 쉬워지고 훈련속도를 빠르게 만드는 장점이 있습니다.