비지도 학습
앞서 머신러닝의 학습은 지도와 비지도 학습이 있다고 했었는데 이제 비지도 학습에 대해 알아보자. 지도학습과의 차이점은 쉽게 타깃에 대한 사전 데이터가 없다는 점이다. 따라서 알고리즘이 스스로 데이터를 판단해서 예측해야 한다. 과일의 데이터를 이용하여 비지도 학습에 대해 알아보자
데이터의 준비하는데 이번에는 사이트의 데이터를 불러와 저장해서 사용해 보자 구글 코랩에서는 '!'를 입력하면 명령프롬포트창(cmd)과 같이 사용이 가능하다. 이를 사용하여 데이터를 불러와 확인해 보자.
!wget http://bit.ly/fruits_300 -O fruits_300.npy
import numpy as np
import matplotlib.pyplot as plt
fruits = np.load('fruits_300.npy')
print(fruits.shape)
-> (300, 100, 100)
fruits 데이터는 여러 과일의 이미지가 흑백으로 저장된 데이터 이다. shape를 확인해 보면 300개의 100* 100 픽셀의 이미지라는 것을 알 수 있다. 한번 첫 번째 과일의 1번째 행에 데이터를 출력해 보자
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]
100*100 이미지의 1번째 행이기 때문에 100개의 데이터가 나온 걸 볼 수 있는데 앞서 이미지가 흑백이미지라고 했는데 흑백의 경우 0~255의 값으로 색상을 정하게 된다. 0 에가까울수록 검은색이고 255에 가까울수록 흰색이다. 그럼 이미지를 출력해 보자 이미지의 경우 imshow() 함수를 통해 넘파이 배열로 지정된 이미지를 그릴 수 있고 안의 매개변수 cmap은 색상을 정하는 것인데 앞서 흑백의 이미 지기 때문에 gray를 사용해 준다. 추가적으로 gray_r을 사용한다면 흰색 백색이 반전되어 배경이 하얀색에 피사체가 검은색 계연인 이미지를 볼 수 있다.
plt.imshow(fruits[200], cmap = "gray")
fruits[0,60, :]
과일의 200번째 데이터는 바나나가 출력되는 걸 알 수 있고 나머지 300개의 데이터에도 이와같은 흑백의 이미지가 있다는 것을 알 수 있다. 다른 이미지도 한번 불러와 보자 matplotlib에서 여러 개의 이미지를 불러오고 싶을 때는 subplots을 사용한다. subplots에는 몇 행 몇 열로 설정할지 정하고 접근할 때는 axs를 통해 어느 위치에 값을 넣을 것인지 정할 수 있다.
fig, axs = plt.subplots(1,2)
axs[0].imshow(fruits[000], cmap ="gray_r")
axs[1].imshow(fruits[100], cmap ="gray_r")
대충 100개의 단위로 과일이 구분됨을 볼 수 있다.
우리가 과일을 구분하기 위해서 생각해 볼 수 있는 방법은 픽셀 단위로 데이터를 분석하는 것인데. 하나의 이미지에 대한 픽셀의 평균을 이용해서 분석을 해보자. 우선 필요한 작업이 100*100의 2차원 배열인 이미지를 1차원 배열로 바꿔주는 것이다. 이는 앞서 배운 reshape를 이용하면 쉽게 사용할 수 있다.
reshape를 통해 1차원으로 바꾼 데이터는 길이가 10000인 1차원 배열인데 이제 각각의 샘플에 대해 평균을 내기 위해서는 배열의 값을 열로 접근해서 평균값을 계산해야 한다. 따라서 axis=1을 사용하면 열에 대한 값이고 평균값은 넘파이에서 제공하는 mean을 사용하면 된다.
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.mean(axis=1))
print(pineapple.mean(axis=1))
print(banana.mean(axis=1))
이제 사과를 예시로 각 샘플 평균값을 확인해 보자
print(apple.mean(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개의 픽셀에 대한 평균값이 나오고 다른 과일들도 이와 비슷한 형태로 나왔을 것이다. 이제 이를 히스토그램으로 확인해 보자.
#히스토그램
import matplotlib.pyplot as plt
# 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", "pinapple", "banana"])
plt.show()
#샘플의 픽셀 평균값으로 비교하기에는 사과와 파인애플이 구분이 잘안됨
결과를 보면 바나나의 경우 확실히 구분이 되지만 사과와 파인애플은 잘 구분이 되지 않는다. 이는 하나의 과일 샘플의 평균을 내서 비교를 했기 때문에 형태가 비슷한 사과와 파인애플은 겹칠 수밖에 없다.
생각보다 해결하는 방법은 간단한데 평균을 열이 아닌 행으로 즉 axis = 0올 하면 된다, 이렇게 한다면 과일의 이미지의 각 픽셀들의 평균을 낼 수 있고 평균된 값을 이미지로 출력한다면 과일들의 평균 이미지를 확인할 수 있다.
#픽셀의 평균값을 이미지 형태로 출력
#각 항목의 픽셀 평균값을 구하고 이미지형태(100X100)으로 바꿔줌
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 = (10,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()
이제 각 과일들의 평균을 알아냈다면 평균을 과일 중 사과를 예측해 보자 일단 평균의 shape에 대해 알아보면
print(apple_mean.shape) => (100,100)
우리가 가지고 있는 과일의 데이터는 (300,100,100)이기 때문에 과일의 데이터에 평균을 빼주게 되면 각 과일 데이터별 오차에 대해 구할 수 있다. 두 데이터의 차원이 다르지만 넘파이 배열간의 빼기에서는 300의 과일 중 하나의 데이터는 똑같은 (100*100)이므로 각 데이터별로 평균을 빼주게 되는 결과가 된다.
abs_diff = np.abs(fruits -apple_mean)
print(abs_diff.shape) => (300,100,100)
abs_mean = np.mean(abs_diff, axis = (1,2))
print(abs_mean.shape) = > (300,)
위의 코드는 1차원 2차원의 평균값을 3차원의 개수인 300개로 만들어 주기 위해서 사용했다.
만약 이미지가 사과의 평균과 비슷하면 오차가 적을 것이다. 따라서 오차를 오름차순으로 배열하여 인덱스에 저장해 주고 10X 10의 플롯을 만들어 각 플롯에 이미지를 넣어주는 코드를 작성해 출력해 보자.
#argsort 는 오름차 순으로 인덱스를 재배열하는것
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")
axs[i,j].axis("off") # 열 바꿈
plt.show()
결과는 매우 성공적으로 오차를 통해 과일을 예측해 냈다. 이를 범위를 바꿔서 해보면 파인애플과 바나나도 동일한결과를 얻을 수 있다. 이렇게 비슷한 데이터가 뭉쳐져 있는 것을 클러스터(군집)이라고 하고 이 군집을 이용하는 방법은 다음에 이어서 하자
'머신러닝' 카테고리의 다른 글
머신 러닝(with Google Colab) - 6일차(3) (0) | 2024.10.25 |
---|---|
머신 러닝(with Google Colab) - 6일차(2) (0) | 2024.10.25 |
머신 러닝(with Google Colab) - 5일차(3) (0) | 2024.10.18 |
머신 러닝(with Google Colab) - 5일차(2) (1) | 2024.10.18 |
머신 러닝(with Google Colab) - 5일차(1) (0) | 2024.10.17 |