Home 개굴캐글개굴 비지도 학습
Post
Cancel

개굴캐글개굴 비지도 학습

Tab study에서 공부한 비지도 학습에 대해 정리해보려 한다.

비지도 학습(Unsupervised Learning)

비지도 학습이란?

비지도 학습이란 학습 Target값을 미리 제공하지 않고 인공지능 모델이 데이터 셋에서 패턴과 상관관계를 찾아 결과를 예측하는 머신러닝 알고리즘이다.

비지도 학습의 예로는 군집화 알고리즘이 대표적이다.

군집화 (Clustering)

군집화는 비지도 학습에 대표적인 예로, 군집화는 개체들을 비슷한 것끼리 그룹을 나누는 것을 말한다.

군집화에는 k-means, GMM, 평균 이동 등 여러가지 알고리즘이 존재하지만 K-means(K평균)알고리즘만 다뤄볼 것이다.

K-means(k평균)

K-means 알고리즘은 처음에 랜덤하게 클러스터 중심을 선택하고 점차 가장 가까운 샘플의 중심으로 이동하는 알고리즘이다. Scikit-learn에 모델이 정의되어 있다.

즉 K-means의 알고리즘 작동 방식은 아래와 같다.

  1. 무작위 k개의 클러스터 중심을 정한다.
  2. 각 샘플에서 가장 가까운 클러스터 중심을 찾아 해당 클러스터의 샘플로 지정한다.
  3. 클러스터에 속한 샘플의 평균값으로 클러스터 중심을 변경한다.
  4. 클러스터 중심에 변화가 없을 때까지 2번으로 돌아가 반복한다.

K-means 실습해보기

데이터 가져오기

1
2
3
4
5
6
!wget https://bit.ly/fruits_300_data -O fruits_300.npy
import numpy as np
import matplotlib.pyplot as plt

fruits = np.load('fruits_300.npy')
print(fruits.shape)
1
(300, 100, 100)

데이터를 확인해보니 3차원 배열인 것을 확인할 수 있다. 알기쉽게 2차원 배열로 바꿔보자.

1
fruits_2d = fruits.reshape(-1, 100*100)
1
(300, 10000)

K-means 모델 학습

1
2
3
from sklearn.cluster import KMeans
km = KMeans(n_clusters = 3, random_state=42)
km.fit(fruits_2d)

n_cluster는 군집화 갯수를 지정할 수 있다.

1
print(km.labels_)
1
2
3
4
5
6
7
8
9
[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]

km.labels_를 통해 군집화된 결과를 확인할 수 있는데 한 눈에 보기 어려우니까 보기 쉽도록 코드를 짜보자.

1
 print(np.unique(km.labels_, return_counts=True))
1
 (array([0, 1, 2], dtype=int32), array([111,  98,  91]))

#### 각 클러스터 출력해보기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 import matplotlib.pyplot as plt
def draw_fruits(arr, ratio=1) :
  n = len(arr) 
  # 한 줄에 10개씩 이미지를 그림 
  rows = int(np.ceil(n/10)) # 샘플 개수를 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 :
        axs[i, j].imshow(arr[i*10+j], cmap='gray_r')
      axs[i, j].axis('off')
  plt.show()
1
draw_fruits(fruits[km.labels_==0])

바나나와 사과는 잘 구별했지만 파인애플은 살짝 구별이 덜 된 것을 확인할 수 있다.

클러스터 중심 찾아보기

K-means 클래스가 최종적으로 찾은 클러스터 중심은 cluster_centers_를 통해 확인할 수 있다.

1
draw_fruits(km.cluster_centers_.reshape(-1, 100, 100), ratio=3)

1
print(km.transform(fruits_2d[100:101]))
1
[[3393.8136117  8837.37750892 5267.70439881]]

transform 메소드를 통해 훈련 데이터 샘플에서 클러스터 중심까지 거리로 변환해준다. 또 데이터를 예측하는 predict() 메서드가 있다. predict결과는 클러스터 중심이 가장 가까운 것이 예측 클래스로 출력된다.

1
print(km.n_iter_)
1
4

k-means 알고리즘은 반복적으로 클러스터 중심을 옮기면서 최적의 클러스터를 찾는데, n_iter_메소드를 통해 반복한 횟수를 알 수 있다.

최적의 k 찾기

k-means 알고리즘의 단점으로는 클러스터 개수를 n_clusters를 통해 사전에 지정해야 하는 것이다. 실전에서는 몇 개의 클러스터가 있는지 알 수 없는데, 적절한 k값을 찾기 위해 엘보우(elbow) 방법이 있다.

엘보우 방법을 설명하기 전에 이너셔(inertia)를 알아보자. 이너셔는 클러스터의 샘플이 얼마나 가깝게 있는지를 나태내는 값이다.

  • 클러스터 개수가 증가 -> 이너셔 감소 (클러스터 개개의 크기는 줄어들기 때문)

클러스터 개수를 증가시키면서 이너셔를 그래프로 그리면 감소하는 속도가 꺾이는 지점이 있는데, 이 지점부터 클러스터 개수를 늘려도 클러스터에 잘 밀집된 정도가 크게 개선되지 않는다.

1
2
3
4
5
6
7
8
9
inertia = []
for k in range(2, 7): 
  km = KMeans(n_clusters=k, random_state=42)
  km.fit(fruits_2d)
  inertia.append(km.inertia_)
plt.plot(range(2, 7), inertia)
plt.xlabel('k')
plt.ylabel('inertia')
plt.show()

k=3에서 그래프의 기울기가 조금 바뀌는 것을 볼 수 있다.

느낀점

타겟값이 정해져있지 않은 비지도 학습 모델에서는 군집화 알고리즘이 핵심인거 같다. 이 알고리즘은 전처리가 중요해보이고 잘 공부해봐야겠다. k-means방법이 아닌 다른 방법도 공부해봐야겠다.

This post is licensed under CC BY 4.0 by the author.