ML
혼자 공부하는 머신러닝 + 딥러닝 6장 K-평균 리뷰
혀내
2022. 6. 10. 13:27
반응형
그렇다면 타깃 데이터를 알지 못해도 머신러닝은 자동으로 같은 과일들을 분류할 수 있을까요?
개념 알고 가기
- 클러스터링 = 군집 알고리즘
- 클러스터 = 덩어리, 모음
K-평균
1. k개의 중심점을 무작위로 잡고 가장 가까운 이미지끼리 묶어 군집을 형성한다.
2. 군집 내부의 평균을 다시 구해 중심점을 평균점으로 옮긴다.
3. 옮긴 중심점을 기준으로 다시 가장 가까운 이미지끼리 묶어 군집을 형성한다.
4. 위의 과정을 더이상 군집에 변경이 없을 때까지 반복한다.
KMeans 클래스
챕터 1과 동일하게 과일 사진 데이터를 준비해보자.
!wget https://bit.ly/fruits_300_data -O fruits_300.npy
import numpy as np
fruits = np.load('fruits_300.npy')
fruits_2d = fruits.reshape(-1, 100*100)
KMeans를 통해 K-평균 방식으로 이미지를 분류할 수 있다.
from sklearn.cluster import KMeans
# 중심점 = 센트로이드
km = KMeans(n_clusters=3, random_state=42)
km.fit(fruits_2d)
# 분류 결과 확인
print(km.labels_)
# 결과
[2 2 2 2 2 0 2 2 2 2 2 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 0 2 0 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 2 0 0 2 2 2 2 2 2 2 2 0 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1]
0, 1, 2로 분류된 데이터가 각각 몇 개인지 확인해보도록 하자. unique는 클래스가 중복되는 데이터를 제거하며 return_counts=True로 설정 시, 각 클래스의 데이터가 몇 개인지 함께 출력한다.
print(np.unique(km.labels_, return_counts=True))
# 결과
(array([0, 1, 2], dtype=int32), array([111, 98, 91]))
plt 모듈로 각 클래스에 분류된 이미지들을 확인해보도록 하자.
import matplotlib.pyplot as plt
def draw_fruits(arr, ratio=1):
n = len(arr) # n: 샘플 개수
# 한 줄에 10개씩 이미지를 그린다. 샘플 개수를 10으로 나누어 전체 행 개수를 계산한다.
rows = int(np.ceil(n/10))
# 행이 1개 -> 열 개수 = 샘플 개수 (그렇지 않으면 10개)
cols = n if rows < 2 else 10
fig, axs = plt.subplots(rows, cols,
figsize=(cols*ratio, rows*ratio), squeeze=False)
for i in range(rows):
for j in range(cols):
if i*10 + j < n: # n 개까지 그림
axs[i, j].imshow(arr[i*10 + j], cmap='gray_r')
axs[i, j].axis('off')
plt.show()
# 첫 번째 클러스터를 살펴보자.
draw_fruits(fruits[km.labels_ == 0])
# 두 번째 클러스터
draw_fruits(fruits[km.labels_ == 1])
# 세 번째 클러스터
draw_fruits(fruits[km.labels_ == 2])
클러스터 중심
클러스터의 중심(평균 이미지)을 확인해보자.
# 센트로이드를 확인하는 방법
draw_fruits(km.cluster_centers_.reshape(-1, 100, 100), ratio=3)
100번째 데이터와 각 센트로이드 사이의 거리를 출력하면 1번째 클래스와 가장 근접함(유사함)을 알 수 있다.
# 100번째 데이터와 각 센트로이드 사이의 거리
print(km.transform(fruits_2d[100:101]))
# 결과
[[3393.8136117 8837.37750892 5267.70439881]]
실제로 0번, 즉 1번째 클래스로 분류되었으며
# 가장 가까운 1번째 클래스에 속함
print(km.predict(fruits_2d[100:101]))
# 결과
[0]
실제 이미지를 출력했을 때 1번째 클래스인 파인애플이 맞다는 걸 확인할 수 있다.
draw_fruits(fruits[100:101])
최적의 k 찾기
군집의 개수를 적절하게 설정해 과대 적합을 방지하고 최적의 값을 구할 수 있다.
inertia = []
for k in range(2, 7):
km = KMeans(n_clusters=k, random_state=42)
km.fit(fruits_2d)
inertia.append(km.inertia_)
# 그래프가 꺾일 때 k 값이 최적의 값
plt.plot(range(2, 7), inertia)
plt.xlabel('k')
plt.ylabel('inertia')
plt.show()
반응형