4 분 소요

🔮 비지도 학습

비지도 학습이란 타깃이 없을 때 사용하는 머신러닝 알고리즘이다. = 사람이 가르쳐 주지 않아도(훈련 세트가 없어도) 데이터에 있는 무언가를 학습.

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

    download1
    ❓ 보통 흑백 샘플 이미지는 바탕이 밝고 물체가 짙은 색! -> 근데 얘는 왜 이렇게 보여?
    💡 흑백 이미지는 사진으로 찍은 이미지를 넘파이 배열로 변환할 대 반전시킨 것! -> 왜? 우리의 관심 대상은 사과니까! 바탕은 중요 X 그러나 컴은 저 사진을 그리는데 바탕을 그리는데 높은 값을 사용하여 바탕에 집중할꺼니까 반전시켜 준 것!
    높은 값(흰색)일 수록 출력값이 커진다.

  • 반전된 넘파이 배열의 이미지를 다시 반전 시키는 방법 : cmap='gray_r'

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

    download2

밝은 부분이 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()
    

    download3

    • 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() 함수 : 어떤 과일의 히스토그램인지 알려준다.

download1

📍 픽셀별 평균값 구하기

❓ 그럼 사과랑 파인애플은 어떻게 구분 ?

💡 픽셀별 평균값을 보자

-> 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() : 막대 그래프를 그려 준다.

download2

픽셀 평균값을 100 * 100 이미지처럼 출력해보기

download3

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. 픽셀별 평균값 -> 절댓값 오차가 작은 사진들을 가져온다.

download1

download2

댓글남기기