1. 과일 데이터 불러오기
▶ 과일 사진 데이터 준비
!wget https://bit.ly/fruits_300 -O fruits_300.npy
: 이전에는 사과, 파인애플, 바나나에 있는 각 픽셀에 평균값을 구해서 가장 가까운 사진을 추출
→ 사과, 파인애플, 바나나 사진인 것을 미리 알고 있었기 때문에 각 과일의 평균을 구할 수 있었음
But 진짜 비지도 학습에서는 어떤 과일이 들어있는지 알지 못함
: k-평균 군집 알고리즘이 평균값을 자동으로 찾아줌
→ 이 평균값이 클러스터의 중심에 위치하기 때문에 클러스터 중심 또는 센트로이드(centroid)라고 부름
: k-평균 알고리즘의 작동방식을 이해하고, 사과, 파인애플, 바나나를 구분하는 비지도 학습 모델 만들어보기!
▶ 넘파이에서 npy 파일 로드
: load() 메서드에 파일 이름을 전달
import numpy as np
fruits = np.load('fruits_300.npy')
fruits_2d = fruits.reshape(-1, 100*100)
: k-평균 모델을 훈련하기 위해 (샘플 개수, 높이, 너비)의 3차원 배열을 (샘플 개수, 높이X너비)의 2차원 배열로 변경
2. k-평균(k-mean) 군집 알고리즘
▶ k-평균 군집 알고리즘
- 무작위로 k개의 클러스터 중심을 정한다
- 각 샘플에서 가장 가까운 클러스터 중심을 찾아 해당 클러스터의 샘플을 지정한다
- 클러스터에 속한 샘플의 평균값으로 클러스터 중심을 변경한다
- 클러스터 중심에 변화가 없을 때까지 2번으로 돌아가 반복한다
▶ 사이킷런 k-평균 알고리즘 KMeans 클래스
from sklearn.cluster import KMeans
km = KMeans(n_clusters=3, random_state=42)
km.fit(fruits_2d)
: 사이킷런의 k-평균 알고리즘은 sklearn.cluster 모듈 아래 KMeans 클래스에서 구현
: n_cluster 매개변수로 클러스터 개수를 지정(클러스터 개수를 3으로 지정)
: 비지도 학습이므로 fit() 메서드에서 타깃 데이터를 사용하지 않음
▶ 군집된 결과를 KMeans 클래스 객체의 labels_속성에 저장
: labels_ 배열의 길이는 샘플 개수와 같음
: 배경은 각 샘플이 어떤 레이블에 해당되는지 나타냄
: n_clusters = 3으로 지정했기 때문에 labels_ 배열의 값은 0, 1, 2 중 하나
print(km.labels_)
▶ 레이블 0, 1, 2로 모은 샘플의 개수 확인
: 레이블값 0, 1, 2 와 레이블 순서에는 어떤 의미도 없음
: 실제 레이블 0, 1, 2가 어떤 과일 사진을 주로 모았는지 알아보려면 직접 이미지를 출력하는 것이 최선
print(np.unique(km.labels_, return_counts=True))
>> 첫 번째 클러스터(레이블0) 91개의 샘플을 모음
>> 두 번째 클러스터(레이블1) 98개의 샘플을 모음
>> 세 번째 클러스터(레이블2) 111개의 샘플을 모음
▶ draw_fruits() 함수로 각 클러스터의 이미지 출력해보기
: draw_fruits() 함수는 (샘플 개수, 높이, 너비)의 3차원 배열을 입력받아 가로로 10개씩 출력
: 샘플 개수에 따라 행과 열의 개수를 계산하고 figsize를 지정함
: figsize는 ratio 매개변수에 비례하여 커짐(ratio의 기본값은 1)
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()
▶ 레이블0, 1, 2 를 그린 결과를 보면 k-평균을 완벽하게 구현해내지는 못함
* 레이블0 그리기
draw_fruits(fruits[km.labels_==0])
* 레이블1 그리기
draw_fruits(fruits[km.labels_==1])
* 레이블2 그리기
draw_fruits(fruits[km.labels_==2])
3. 클러스터 중심
▶ 클러스터 중심 이미지로 출력해보기
draw_fruits(km.cluster_centers_.reshape(-1, 100, 100), ratio=3)
▶ fruits[100:101]에 대해 알아보기
* km.transform()
print(km.transform(fruits_2d[100:101]))
* km.predict()
print(km.predict(fruits_2d[100:101]))
* fruits[100:101]에 해당하는 과일 그려보기
draw_fruits(fruits[100:101])
▶ km.n_iter_
print(km.n_iter_)
4. 최적의 k 찾기
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.show()
댓글