[chap 6-1] 군집 알고리즘
🔮 비지도 학습
비지도 학습이란 타깃이 없을 때 사용하는 머신러닝 알고리즘이다. = 사람이 가르쳐 주지 않아도(훈련 세트가 없어도) 데이터에 있는 무언가를 학습.
1️⃣ 과일 사진 데이터 준비하기
!wget https://bit.ly/fruits_300_data -O fruits_300.npy
를 입력하면 코랩으로 다운이 되는데, 이때 저 0같은 O같은 친구는 대문자 O 이고, -O fruits_300.npy
가 없다면 fruits_300_data라는 이름으로 다운이 된다.
-
다운 확인하기 확인하는 방법은 간단하다.
np.load
를 통해서 매개변수로 파일 이름만 넣어주면 된다! 여기서 -O를 소문자로 썼다가,, 시간 낭비,,,,왜 소문자로 썼지,,,,,,,,,,? 여튼 대문자 O라는거!import numpy as np import matplotlib.pyplot as plt fruits = np.load("fruits_300.npy") print(fruits.shape) print(fruits[0, 0, :]) >>> (300, 100, 100) [ 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]
- fruits.shpae : 샘플이 총 300개, 이미지 높이가 100, 너비가 100인 이미지들
- fruits[0, 0, :] : 샘플 첫 번째, 첫 번째 행에 있는 픽셀 100개를 가져온다
plt.imshow(fruits[0], cmap='gray') plt.show()
❓ 보통 흑백 샘플 이미지는 바탕이 밝고 물체가 짙은 색! -> 근데 얘는 왜 이렇게 보여?
💡 흑백 이미지는 사진으로 찍은 이미지를 넘파이 배열로 변환할 대 반전시킨 것! -> 왜? 우리의 관심 대상은 사과니까! 바탕은 중요 X 그러나 컴은 저 사진을 그리는데 바탕을 그리는데 높은 값을 사용하여 바탕에 집중할꺼니까 반전시켜 준 것!
높은 값(흰색)일 수록 출력값이 커진다. -
반전된 넘파이 배열의 이미지를 다시 반전 시키는 방법 :
cmap='gray_r'
plt.imshow(fruits[0], cmap='gray_r') plt.show()
밝은 부분이 0에 가깝고 짙은 부분이 255에 가까운 값이며 255에 가까워질수록 픽셀값이 커지는 것이므로 출력값도 커진다!
-
다른 과일들도 출력해보기
fig, axs = plt.subplots(1, 2) axs[0].imshow(fruits[100], cmap="gray_r") axs[1].imshow(fruits[200], cmap="gray_r") plt.show()
- plt.subplots(row, column, index) : 여러 개의 그래프를 배열처럼 쌓을 수 있도록 도와준다. 위 코드에서는 1행 2열로 지정했으므로 위와 같은 사진이 출력되는 것이다. index는 그래프 위치 조정 가능.
- fig : 두 개의 axs를 가지는 하나의 figure(빈 종이)
- axs[0] : 파인애플 이미지
- axs[1] : 바나나 이미지
2️⃣ 픽셀값 분석하기
📍 픽셀 데이터 세팅하기
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)
- fruit[from:to] : from부터 to까지의 인덱스에 해당되는 과일을
- reshape(-1, 100*100) : 각 이미지당 10000개의 배열로 합친다. -> 100 * 10000의 2차원 배열(행: 이미지 한개의 픽셀 전체)
📍 샘플의 평균값 구하기
print(apple.mean(axis=1))
print(pineapple.mean(axis=1))
print(banana.mean(axis=1))
- axis=1 : 하나의 행을 보겠다. 왜냐면 행 하나가 이미지 하나에 대한 픽셀들을 가지고 있으니까
각 출력값 당
[ 99.3239 87.1622 97.193 97.4689 98.8892 97.8819 95.1444 92.9461
95.8412 96.9487 93.2863 101.2771 91.6511 98.3901 84.3277 100.7017
99.0229 87.5298 99.4109 91.8568 90.3877 99.5066 95.8498 96.0728
100.0062 95.5283 95.2715 98.1624 93.1395 99.1666 99.9519 96.732
94.16 100.7644 101.1263 98.2852 98.5354 101.3809 95.4862 93.1256
87.6404 93.7146 94.7279 85.5131 95.0937 95.3236 92.7696 94.4375
99.36 95.8924 97.8221 99.4014 99.325 95.025 97.5771 97.3511
99.4891 97.366 101.0062 91.2304 95.2824 95.3544 101.4657 97.5239
98.8419 96.746 98.2922 96.3969 81.9464 93.4927 97.3872 82.4883
95.3665 95.2541 101.3074 97.2391 95.4544 100.5576 100.2927 94.3088
95.7401 97.0982 96.9559 92.9114 97.4164 100.769 97.808 99.2481
101.0643 94.8173 99.2639 98.8539 97.2198 97.0201 94.5039 98.097
95.0201 98.8078 99.4634 100.0257]
이런식으로 이미지 당 10000개의 픽셀의 평균값이 나오는데, 이렇게 나온 100개의 원소를 다시 평균을 내어서 보면!
-
사과 샘플 하나 당 10000개의 픽셀 평균값의 평균값 : 92.987736
-
파인애플 샘플 하나 당 10000개의 픽셀 평균값의 평균값 : 96.260623
-
바나나 샘플 하나 당 10000개의 픽셀 평균값의 평균값 : 34.597277000000005
대략 바나나인지 아닌지는 픽셀 평균값으로 알 수 있다. 구분이 되니까! 이거를 히스토그램으로 그려보면
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
- hist() : 히스토그램을 그려준다.
- aplha : 1보다 작게 하면 투명도를 줄 수 있다.
- legend() 함수 : 어떤 과일의 히스토그램인지 알려준다.
📍 픽셀별 평균값 구하기
❓ 그럼 사과랑 파인애플은 어떻게 구분 ?
💡 픽셀별 평균값을 보자
-> 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()
- figsize(width, height) : 창 크기 생성
- bar() : 막대 그래프를 그려 준다.
픽셀 평균값을 100 * 100 이미지처럼 출력해보기
3️⃣ 평균값과 가까운 사진 고르기
300개의 사진 중 사과 픽셀 평균값과 비슷한 사진들을 찾는다
HOW? -> 절댓값 오차 사용
abs_diff = np.abs(fruits - apple_mean)
abs_mean = np.mean(abs_diff, axis=(1, 2))
print(abs_mean.shape) # (300,)
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()
- abs_diff : 크기 (300, 100, 100)의 배열, 각 샘플에 대한 평균을 구하기 위해서
abs_mean = np.mean(abs_diff, axis=(1, 2))
: axis=(1, 2)로 지정 -> 다시 이에 대한 평균을 구함-
apple_index = np.argsort() : 작은 값부터 정렬해서 100개의 값의 인덱스를 갖고 있는 변수 apple_index. -> apple_index의 인덱스 부분 규칙 : apple_index는 1차원 배열, 그려야되는 그래프는 2차원 배열 형식 그래서 i*10 + j 이렇게 쓴 것!
- 군집 : 비슷한 샘플끼리 그룹으로 모으는 작업, 비지도 학습 작업 중 하나
- 클러스터 : 군집 알고르즘에서 만든 그룹
🌗 결과
샘플 평균값 으로 바나나와 바나나가 아닌 과일을 분류할 수 있었다. 그러나 사과와 파인애플은 샘플 평균값이 비슷하게 나옴 -> sol. 픽셀별 평균값 -> 절댓값 오차가 작은 사진들을 가져온다.
댓글남기기