비지도 학습(unsupervised learning)
지도학습이 특정 입력에 대하여 올바른 정답이 있는 데이터가 주어지는 학습이라면, 비지도 학습은 특정 입력에 대해 정답이 없는 데이터가 주어지는 학습이다.
군집화(clustering)
- 과일 사진 데이터 준비하기
!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')
넘파이에서 npy 파일을 로드하는 방법
print(fruits.shape)
fruits 배열의 크기 확인
(300, 100, 100)
300개의 샘플이 있고, 높이가 100이고 너비가 100인 이미지가 있다. 이미지 크기가 100x100이고, 각 픽셀이 넘파이 배열의 원소 하나에 대응해 배열의 크기가 100x100이라는 의미이다.
print(fruits[0,0,:])
첫 번째 이미지의 첫 번째 행을 출력
[ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1
2 2 2 2 2 2 1 1 1 1 1 1 1 1 2 3 2 1
2 1 1 1 1 2 1 3 2 1 3 1 4 1 2 5 5 5
19 148 192 117 28 1 1 2 1 4 1 1 3 1 1 1 1 1
2 2 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]
plt.imshow(fruits[0], cmap='gray')
plt.show()
imshow() : numpy배열로 저장되어 있는 값을 이미지로 출력할 수 있도록 해주는 함수
plt.imshow()에는 인자로 cmap이 존재하는데 이를 통해 출력 컬러맵을 설정할 수 있다. (default = viridis, 단녹색(?))
0에 가까울수록 검게 나타나고 값이 높아질수록 밝게 나타난다.
plt.imshow(fruits[0], cmap='gray_r') #흑백이미지 반전
plt.show()
cmap을 gray_r로 주면 반전해서 보여준다
컴퓨터는 알고리즘이 어떤 출력을 만들기 위해 덧셈과 곱셈을 하는데 픽셀값이 0이면 출력이 0이 되어서 아무 의미가 없어진다. 픽셀값이 높을수록 출력값도 커지기 때문에 의미를 부여하기 좋다.
fig, axs = plt.subplots(1, 3)
axs[2].imshow(fruits[0], cmap='gray_r') #사과
axs[0].imshow(fruits[100], cmap='gray_r') #파인애플
axs[1].imshow(fruits[200], cmap='gray_r') #바나나
matplotlib.pyplot.subplots(nrows=1, ncols=1, *, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None, **fig_kw)
맷플롯립의 subplots() 함수를 사용하면 여러 개의 그래프를 배열처럼 쌓을 수 있다.
nrows와 ncols로 행과 열을 지정해서 그래프의 개수를 지정할 수 있다.
- 픽셀값 분석하기
apple = fruits[0:100].reshape(-1, 100*100)
pineapple = fruits[100:200].reshape(-1, 100*100)
banana = fruits[200:300].reshape(-1, 100*100)
fruits 데이터를 사과, 파인애플, 바나나로 각각 나누고 넘파이 배열을 나눌 때 100x100 이미지를 펼쳐서 길이가 10000인 1차원 배열로 만든다(* 원래는 (100, 100))
apple, pineapple, banana의 배열 크기는 (100, 10000)이다
print(apple.mean(axis=1))
mean() : 평균값을 계산할 때, axis로 행 단위 또는 열 단위로 평균을 구할 수 있음
- axis 0 : 열 단위로 평균을 반환
- axis 1 : 행 단위로 평균을 반환
>>각 샘플 별로 평균을 낼 것이기 때문에 가로로 나열해서 axis = 1로 지정하여 평균을 계산한다
[ 88.3346 97.9249 87.3709 98.3703 92.8705 82.6439 94.4244 95.5999
90.681 81.6226 87.0578 95.0745 93.8416 87.017 97.5078 87.2019
88.9827 100.9158 92.7823 100.9184 104.9854 88.674 99.5643 97.2495
94.1179 92.1935 95.1671 93.3322 102.8967 94.6695 90.5285 89.0744
97.7641 97.2938 100.7564 90.5236 100.2542 85.8452 96.4615 97.1492
90.711 102.3193 87.1629 89.8751 86.7327 86.3991 95.2865 89.1709
96.8163 91.6604 96.1065 99.6829 94.9718 87.4812 89.2596 89.5268
93.799 97.3983 87.151 97.825 103.22 94.4239 83.6657 83.5159
102.8453 87.0379 91.2742 100.4848 93.8388 90.8568 97.4616 97.5022
82.446 87.1789 96.9206 90.3135 90.565 97.6538 98.0919 93.6252
87.3867 84.7073 89.1135 86.7646 88.7301 86.643 96.7323 97.2604
81.9424 87.1687 97.2066 83.4712 95.9781 91.8096 98.4086 100.7823
101.556 100.7027 91.6098 88.8976]
↑ 사과 샘플 100개에 대한 픽셀 평균값
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()
사과, 파인애플, 바나나에 대한 히스토그램을 그려서 평균값이 어떻게 분포되어 있는지 확인해본다
matplotlib.pyplot.hist(x, bins=None, range=None, density=False, weights=None, cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, color=None, label=None, stacked=False, *, data=None, **kwargs)
x : 데이터 값으로 리스트나 ndarray 타입으로 넣는다
alpha : 투명도, 0.0에서 1.0 사이의 값을 갖는다
바나나 사진은 픽셀값이 낮은 쪽에 집중되어 있고, 사과와 파인애플은 높은 쪽에 집중되어 있음을 볼 수 있다.
- 바나나는 사진에서 차지하는 영역이 작아서 평균값이 작다
>> 사과와 파인애플은 많이 겹쳐있어서 픽셀값만으로 구분하기가 어렵다
>>>>각 샘플의 평균값이 아니라 픽셀별 평균값을 비교한다. 즉, 전체 샘플에 대해 각 픽셀의 평균을 계산한다
>>>>>>axis=0을 사용한다!
100*100개의 픽셀에 대한 평균값을 계산한다
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()
fig : 전체 액자 figure에 대한 변수
axs : 액자 내 여러 개의 액자에 대한 리스트
bar(x축 데이터, y축 데이터) : x축은 픽셀값, y축은 사과, 바나나, 파인애플을 픽셀 평균한 값을 가진 막대그래프
픽셀 평균값을 100x100으로 바꿔서 2차원 배열로 변경해 이미지처럼 출력한다.
과일 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()
- 평균값과 가까운 사진 고르기
abs_diff = np.abs(fruits - apple_mean)
abs_mean = np.mean(abs_diff, axis=(1,2)) #300개의 원소로 이루어진 1차원 배열
print(abs_mean.shape)
np.abs() : 절댓값을 계산하는 함수, 배열을 입력하면 모든 원소의 절댓값을 계산하여 입력과 동일한 크기의 배열을 반환한다.
절댓값 오차를 사용해 사과 사진의 평균값인 apple_mean과 가장 가까운 사진을 고른다
> fruits 배열(300개의 과일이 있는 전체 데이터)에 있는 모든 샘플에서 apple_mean(사과 평균값)을 뺀 절댓값의 평균을 계산한다 -> 차이가 크냐 작냐가 중요
(300,)
abs_mean은 300개의 원소를 가진 1차원 배열
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개를 고른다
np.argsort() : 작은 값부터 순서대로 데이터의 인덱스를 반환한다.
>> 작은 것에서 큰 순서대로 나열한 abs_mean 배열의 인덱스를 반환
>> 어느 위치에 있는 사과가 가장 작은지 알기 위해, sorting해서 순서대로 나열된 배열의 인덱스를 찾아야함.
2중 for문을 돌면서 10개의 행과 열에 이미지를 출력한다. axs는 (10, 10) 크기의 2차원 배열이므로 i, j를 사용하여 서브 그래프의 위치를 지정한다.
apple_mean과 가장 가까운 사진 100개를 골랐더니 모두 사과가 나왔다.
>> 이미지에 있는 픽셀의 평균값을 계산해서, 이 평균값과 가장 가까운 이미지를 찾으면 새 이미지를 잘 분류할 수 있다.(사용자가 올린 이미지)
>> 군집(clustering) : 비슷한 샘플끼리 그룹으로 모으는 작업(비지도 학습 작업)
클러스터(cluster) : 군집 알고리즘으로 모은 샘플 그룹
여기에서는 타깃값을 알고 있어서 어떤 샘플이 어떤 과일인지 미리 알고 있었기 때문에 사과 사진의 평균값을 알 수 있었다. -> 실제 비지도 학습에서는 타깃이 없는 사진을 사용해야한다! -> k-평균 알고리즘
'머신러닝 + 딥러닝' 카테고리의 다른 글
[혼공머신] CHAPTER 06-3 주성분 분석 (0) | 2021.10.27 |
---|---|
[혼공머신] CHAPTER 06-2 k-평균 (0) | 2021.10.27 |
[혼공머신] CHAPTER 05-3 트리의 앙상블 (0) | 2021.10.07 |
[혼공머신] CHAPTER 05-2 교차검증과 그리드 서치 (0) | 2021.10.04 |
[혼공머신] CHAPTER 05-1 결정 트리 (0) | 2021.10.02 |