머신러닝 기초 | 군집 알고리즘(2) | k-평균 군집 알고리즘 | KMeans 클래스 | draw_변수명() 함수로 클러스터 중심 이미지 출력하기 | 최적의 k 찾기 | 비지도 학습

    728x90

     

    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-평균 군집 알고리즘

    1. 무작위로 k개의 클러스터 중심을 정한다
    2. 각 샘플에서 가장 가까운 클러스터 중심을 찾아 해당 클러스터의 샘플을 지정한다
    3. 클러스터에 속한 샘플의 평균값으로 클러스터 중심을 변경한다
    4. 클러스터 중심에 변화가 없을 때까지 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()

    728x90

    댓글