AI/혼자공부하는머신러닝딥러닝

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

inthyes 2024. 1. 23. 15:53

비지도 학습은 머신러닝의 한 종류로 훈련 데이터에 타깃이 없다. 타깃이 없기 때문에 외부의 도움 없이 스스로 유용한 무언가를 학습해야 한다. 대표적인 비지도 학습 작업으로 군집, 차원 축소 등이 있다.

과일 사진 데이터 준비

파일을 읽기 위해 코랩으로 다운로드한다. 

!wget https://bit.ly/fruits_300_data -O fruits_300_data.npy
import numpy as np
import matplotlib.pyplot as plt

 

넘파이에서 npy파일을 로드하기 위해 load()메서드에 파일 이름을 전달한다.

fruits = np.load('fruits_300_data.npy')
print(fruits.shape)

이 배열의 첫 번째 차원(300)은 샘플의 개수, 두 번째 차원(100)은 이미지 높이, 세 번째 차원(100)은 이미지 너비를 의미한다.

이미지 크기는 100 * 100이며 각 픽셀은 넘파이 배열의 원소 하나에 대응한다.

 

첫 번째 이미지의 첫 번째 행을 출력하는 코드이다.

print(fruits[0,0,:])

첫 번째 행에 있는 픽셀 100개에 들어 있는 값을 출력한 것이다. 흑백 사진을 담고 있기 때문에 0~255 사이의 정수값을 가진다.

 

맷플로립의 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개씩 들어있다. 바나나와 파인애플 이미지도 출력해보자.

fig, axs = plt.subplots(1, 2)
axs[0].imshow(fruits[100], cmap = 'gray_r')
axs[1].imshow(fruits[200], cmap = 'gray_r')
plt.show()

subplot()함수를 사용하면 여러 개의 그래프를 배열처럼 쌓아 출력할 수 있다.

subplot(1,2)로 지정할 경우 하나의 행과 두개의 열로 출력된다.

 

픽셀값 분석하기

fruits 데이터를 과일 종류로 각각 나누고자 한다.

 

넘파이 배열을 나눌 때 100 * 100이미지를 펼쳐서 10,000인 1차원 배열로 생성한다.

배열에서 순서대로 100개씩 선택하기 위해 슬라이싱 연산자를 사용하고 reshape()메서드를 사용해 두 번째 차원과 세 번째 차원을 합친다. 첫 번째 차원을 -1로 지정해 자동으로 남은 차원을 할당하도록 한다.

apple = fruits[0:100].reshape(-1, 100 * 100)
pineapple = fruits[100:200].reshape(-1, 100 * 100)
banana = fruits[200:300].reshape(-1, 100 * 100)

 

사과의 배열을 확인해본다.

print(apple.shape)

 

axis는 배열의 '축'을 의미한다. axis = 1일 때는 열 방향으로 계산하고, axis = 0일 때는 행 방향으로 계산을 수행한다.

 

샘플의 평균값을 구하기 위해 axis = 1로 지정하여 평균을 계산한다.

print(apple.mean(axis = 1))

 

히스토그램을 그려 평균값이 어떻게 분포되어 있는지 확인이 가능하다.

 

히스토그램이란?

구간별로 값이 발생한 빈도를 그래프로 표시한 것이다. 보통 x축이 값의 구간(계급)이고 y축은 발생 빈도(도수)이다.

 

맷플롯립의 hist()함수를 사용한다. 이 때 alpha 매개변수를 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()

위 히스토그램은 사과나 파인애플을 픽셀값만으로 구분하기에 어려움이 존재한다.

이 문제를 해결하기 위해 샘플의 평균값이 아니라 픽셀별 평균값을 비교해보고자 한다.

픽셀의 평균 계산은 axis = 0으로 지정하면 된다.

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 * 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)

np.argsort()함수를 사용해 작은 것에서 큰 순서대로 나열한 배열의 인덱스를 출력한다.

apple_mean과 오차가 가장 작은 샘플 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()

2중 for 반복문을 순회하면서 10개의 행과 열에 이미지를 출력한 결과이다.

 

군집은 비슷한 샘플끼리 하나의 그룹으로 모으는 대표적인 비지도 학습 작업이다. 군집 알고리즘으로 모은 샘플 그룹을 클러스터라고 부른다.

 

위의 모든 과정은 타깃값을 인지한 상태였기 때문에 평균값을 계산해서 가장 가까운 과일을 찾을 수 있었다. 하지만 실제 비지도 학습에서는 타깃값을 모르기 때문에 샘플의 평균값을 미리 구하는 것은 불가능하다.

'AI > 혼자공부하는머신러닝딥러닝' 카테고리의 다른 글

[ML] 06-3 주성분 분석  (1) 2024.01.26
[ML] 06-2 k-평균  (1) 2024.01.23
[ML] 05-3 트리의 앙상블  (1) 2024.01.23
[ML] 05-2 교차 검증과 그리드 서치  (1) 2024.01.22
[ML] 05-1 결정 트리  (1) 2024.01.22