Python/ML & DL 공부

[ML] 06-1 군집 알고리즘

dori_0 2022. 3. 12. 10:40

혼자 공부하는 머신러닝+딥러닝 책을 바탕으로 공부한 내용입니다.

 

CH6 비지도 학습 ①

비슷한 샘플끼리 모으기

 


 

흑백 사진을 분류하기 위해 여러 가지 아이디어를 내면서 비지도 학습과 군집 알고리즘에 대해 이해하자
해야 할 일 : 여러 과일 사진을 같은 과일끼리 분류하기

 

▶ 과일 사진 데이터 준비하기

타깃이 없을 때 사용하는 머신러닝 알고리즘은 비지도 학습이다.

사과, 바나나, 파인애플이 각각 100개씩 들어있는 데이터로 군집 알고리즘을 사용해보자

# 과일 사진 데이터 불러오기
import wget
url = "https://bit.ly/fruits_300_data" 
wget.download(url)

import numpy as np
import matplotlib.pyplot as plt

fruits = np.load('fruits_300_data')
fruits.shape  #(300, 100, 100)
  • 첫번째 차원(300)은 샘플의 개수, 두번째 차원(100)은 이미지 높이, 세번째 차원(100)은 이미지 너비

 

 

fruits 중 첫번째 이미지의 첫번째 행을 출력해보자

# 첫번째 이미지의 첫번째 행 출력
print(fruits[0, 0, :])

 

맷플롯립의 imshow() 함수를 사용하여 넘파이 배열로 저장된 이미지를 그려보자

# 그림으로 그려보기
plt.imshow(fruits[0], cmap='gray')
plt.show()

  • 0에 가까울수록 검게, 255에 가까울 수록 밝게 표시된다.
  • 우리가 보는 것과 컴퓨터가 처리하는 방식이 다르므로 종종 흑백 이미지를 반전하여 사용한다.
  • cmap='gray_r'로 지정하면 우리 눈에 보기 좋게 출력한다

 

plt.imshow(fruits[0], cmap='gray_r')
plt.show()

  • 밝은 부분은 0에 가깝고 짙은 부분은 255에 가깝다

 

 

이번에는 바나나와 파인애플 이미지도 출력해보자

이 데이터의 처음 100개는 사과, 그 다음 100개는 파인애플, 마지막 100개는 바나나이다.

# 바나나, 파인애플 이미지도 출력해보기
fig, axs = plt.subplots(1, 2)
axs[0].imshow(fruits[100], cmap='gray_r')
axs[1].imshow(fruits[200], cmap='gray_r')
plt.show()

  • 맷플롯립의 subplots() 함수를 사용하면 여러 그래프를 배열처럼 쌓을 수 있다.

 

 

▶ 픽셀값 분석하기

이제 사용하기 쉽도록 fruits 데이터를 사과, 파인애플, 바나나로 각각 나눠보자.

넘파이 배열을 나눌 때 100 X 100 이미지를 펼쳐 길이가 10,000인 1차원 배열로 만들 것이다.

# fruits 데이터 과일별로 나누기
apple = fruits[0:100].reshape(-1, 100*100)
pineapple = fruits[100:200].reshape(-1, 100*100)
banana = fruits[200:300].reshape(-1, 100*100)
apple.shape, pineapple.shape, banana.shape

  • reshape에서 첫번째 차원을 -1로 지정하면 자동으로 남은 차원을 할당한다

 

 

이제 apple, pineapple, banana 배열에 들어있는 과일별 픽셀 평균값을 계산해볼 것이다

먼저 사과 샘플 100개의 픽셀 평균값을 확인해보자

# 사과 샘플 100개의 픽셀 평균값
print(apple.mean(axis=1))

 

사과와 마찬가지로 파인애플, 바나나의 평균값도 구하여 히스토그램을 그려보자

# 픽셀 평균값 히스토그램
plt.hist(np.mean(apple, axis=1), alpha=0.8)
plt.hist(np.mean(pineapple, axis=1), alpha=0.8)
plt.hist(np.mean(banana, axis=1), alpha=0.8)
plt.legend(['apple', 'pineapple', 'banana'])
plt.show()

  • 바나나는 픽셀 평균값만으로 사과, 파인애플과 확실히 구분할 수 있다.
  • 바나나 사진의 평균값이 작은 이유는 사진에서 차지하는 영역이 작기 때문이다
  • 사과, 파인애플은 픽셀값만으로 구분하기 어렵다.

 

 

이번에는 샘플의 평균값이 아닌 픽셀별 평균값을 비교해보자

# 전체 샘플에 대한 각 픽셀의 평균
fig, axs = plt.subplots(1, 3, figsize=(20,5))
axs[0].bar(range(10000), np.mean(apple, axis=0))
axs[1].bar(range(10000), np.mean(pineapple, axis=0))
axs[2].bar(range(10000), np.mean(banana, axis=0))
plt.show()

  • 과일마다 값이 높은 구간이 다르므로 이를 이용하면 과일을 구분 할 수 있을 것 같다

 

 

이제 픽셀 평균값을 100 X 100 크기로 바꾸고 이미지처럼 출력하여 대표 이미지를 만들어보자

# 대표 이미지 출력해보기
apple_mean = np.mean(apple, axis=0).reshape(100, 100)
pineapple_mean = np.mean(pineapple, axis=0).reshape(100, 100)
banana_mean = np.mean(banana, axis=0).reshape(100, 100)

fig, axs = plt.subplots(1, 3, figsize=(20, 5))
axs[0].imshow(apple_mean, cmap='gray_r')
axs[1].imshow(pineapple_mean, cmap='gray_r')
axs[2].imshow(banana_mean, cmap='gray_r')
plt.show()

  • 이 대표 이미지와 가까운 사진을 고르면 사과, 파인애플, 바나나를 구분할 수 있을 것 같다

 

 

▶ 평균값과 가까운 사진 고르기

사과 사진의 평균값인 apple_mean과 가장 가까운 사진을 골라보자

fruits의 모든 샘플에서 apple_mean을 뺀 절댓값을 평균을 계산하면 된다

# 각 샘플에 대한 사과와의 절댓값 오차 평균
abs_diff = np.abs(fruits - apple_mean)
abs_mean = np.mean(abs_diff, axis=(1, 2))
print(abs_mean.shape)  #(300,)
  • 각 샘플에 대한 평균을 구하기 위해 axis에 두번째, 세번째 차원을 모두 지정해줌

 

 

이제 이 값이 가장 작은 순서대로 100개를 골라 10 X 10 격자로 이루어진 그래프를 그려보자

# 오차가 적은 100개 골라내기
apple_index = np.argsort(abs_mean)[:100]

# 그려보기
fig, axs = plt.subplots(10, 10, figsize=(10,10))
for i in range(10):
    for j in range(10):
        axs[i, j].imshow(fruits[apple_index[i*10 + j]], cmap='gray_r')
        axs[i, j].axis('off')
plt.show()

  • apple_mean과 가장 가까운 사진 100개를 골랐더니 모두 사과임을 확인할 수 있다.

 

 

이번에는 바나나의 평균값과 가까운 사진 100개를 골라보자

abs_diff2 = np.abs(fruits - banana_mean)
abs_mean2 = np.mean(abs_diff2, axis=(1, 2))

# 오차가 적은 100개 골라내기
banana_index = np.argsort(abs_mean2)[:100]

# 그려보기
fig, axs = plt.subplots(10, 10, figsize=(10,10))
for i in range(10):
    for j in range(10):
        axs[i, j].imshow(fruits[banana_index[i*10 + j]], cmap='gray_r')
        axs[i, j].axis('off')
plt.show()

  • 완벽하게는 분류하지 못한 것을 확인할 수 있다.

 

 

우리는 과일 데이터를 분류할 때 데이터 안에 사과, 파인애플, 바나나가 있다는 것을 알고 있었다

하지만 실제 비지도 학습에서는 타깃값을 모르므로 샘플의 평균값을 미리 구할 수 없다.

타깃값을 모를 때 세 과일의 평균값을 찾는 방법을 다음 장에서 공부해보자

 

 

 

▶ 정리

  1. 비지도 학습 - 머신러닝의 한 종류로 훈련 데이터에 타깃이 없는 것
    • 타깃이 없으므로 외부의 도움 없이 스스로 무언가를 학습해야 함
    • 대표적인 비지도 학습 작업은 군집, 차원 축고 등
  2. 군집 - 비슷한 샘플끼리 그룹으로 모으는 작업, 대표적인 비지도 학습 작업 중 하나
  3. 클러스터 - 군집 알고리즘에서 만든 그룹

 

'Python > ML & DL 공부' 카테고리의 다른 글

[ML] 06-3 주성분 분석  (0) 2022.03.12
[ML] 06-2 k-평균 알고리즘  (0) 2022.03.12
[ML] 05-3 트리의 앙상블  (0) 2022.03.11
[ML] 05-2 교차 검증과 그리드 서치  (0) 2022.03.11
[ML] 05-1 결정 트리  (0) 2022.03.11