상세 컨텐츠

본문 제목

[PLAYDATA] 데이터 엔지니어링 9월 3주차 9/13

PLAYDATA/PLAYDATA데일리노트

by Na느님 2023. 9. 13. 11:34

본문

  • 9월 13일
비지도학습에 대해 다룬다.

 

 

비지도 학습이란?

비지도 학습(Unsupervised Learning)은 타깃이 없을 때 사용하는 머신러닝 알고리즘이다.

 

 

이미지 인식

1. 먼저 이미지 파일들을 numpy 패키지로 다루기 위해 데이터셋에 필요한 이미지 파일들을 하나의 npy 확장자로 변환해야 한다.

 

2. 이미지를 보여줄 matplotlib패키지를 로드한다.

import numpy as np

import matplotlib.pyplot as plt

 

3. npy파일을 Python의 변수로 전달하는 방법은 np.load(<npy_filename.npy>)함수를 사용하면 된다.

<numpy.ndarray> = np.load(<npy_filename.npy>)

 

4. 3번의 <numpy.ndarray> 변수는 3차원 행렬인데, 첫 차원은 이미지 갯수, 두번째 차원은 이미지 height, 세번째 차원은 이미지 width이다.

-> <numpy.ndarray>.shape 멤버변수를 통해 각 차원마다 줄의 갯수를 확인할 수 있다.

 

(중요) numpy.ndarry 자료형의 차원 접근은 콤마(,)로 구분한다.

e.g.) car[0, 0, :]

 

5. plt.imshow(<numpy.ndarray>[, cmap=<color>])함수를 사용하여 matplotlib패키지로 이미지를 시각화할 수 있다.

cmap: 흑백은 gray, 흑백반전은 gray_r이다.

 

(중요) 이미지에서 더 중요한 사물은 어두운것 보다 밝은게 훨씬 유리하다. 그 이유는 밝은 픽셀이 높은 값을 가지도록 하였기 때문에 더 영향이 크다.

 

6. NxN 행렬 형태의 이미지를 Mx1 형태로 펼쳐준다.

-> reshape함수를 사용한다. (행의 갯수가 특정 클래스의 데이터 갯수고, 열의 갯수를 픽셀 갯수로 한다)

 

7. 이제 각 행렬당 각자의 클래스에 해당하는 이미지들이 모여있게 된다. 이제 데이터는 준비되었다. 이미지 인식에 사용될 핵심 알고리즘을 적용한다.

여기서는 평균을 이용하기로 한다.

<numpy.ndarray>.mean(axis = 0/1)

이렇게 하면 각 줄의 평균이 평균벡터의 element에 저장된다.

axis옵션이 0이라면 열을 기준으로 평균을 계산하고, 1이라면 행을 기준으로 평균을 계산한다.

NxM 행렬의 mean을 구한다면, axis = 0일 때, M개의 element를 갖는 1xM행렬이 나올 것이고,

axis = 1일 때, N개의 element를 갖는 1xN행렬이 나올 것이다.

<이하생략>

 

k-평균

k-평균은 특정 클래스의 평균값을 자동으로 찾아주는 비지도학습 알고리즘이다.

-> 이 평균값은 특정 클러스터(군집)의 중심에 위치한다.

 

작동 원리

1. 무작위로 k개의 클러스터 중심을 배치한다.

2. 각 샘플을 기준으로 해당 샘플에서 가장 가까운 클러스터 중심이 그 샘플이 들어갈 클러스터가 된다. 이를 모든 샘플에 대해서 적용한다.

3. 각 클러스터의 평균을 구하고 그 값으로 클러스터 중심을 변경한다.

4. 클러스터 중심 변화 없을 때까지 2번으로 돌아가서 반복.

 

그러니까 target없이 "평균" 값이 유사한 데이터들을 모으겠다는 것이다.

 

 

k-평균 구현

import sklearn.cluster import KMeans

<km_obj> = KMeans(n_clusters = <n>[, random_state = <n>])

km.fit(<train_data>)

n_clusters옵션에 k값이 들어간다(클러스터 갯수).

여기서는 비지도학습이기 때문에 fit함수에 target 데이터가 들어가지 않는다.

 

결과 확인

k-평균의 결과는 <km_obj> 객체의 labels_멤버변수에 있다. labels_ 라는 배열의 원소갯수는 샘플의 갯수와 같다.

labels_는 각 샘플이 어떤 군집에 속해 있는지를 나타내준다.

학습 결과 지정된 클러스터의 중심cluster_centers_ 멤버변수에 있다.

n_iter_ 멤버변수는 클러스터 중심을 찾기 위해 알고리즘이 반복된 횟수이다.

 

최적의 k 찾기

앞에서는 프로그래머가 직접 n_clusters 옵션을 지정해 주었다. 그 말은 k값을 이미 알고 있다는 뜻이다. 그러나 진정한 비지도 학습은 클래스(클러스터)의 종류가 몇 개인지 조차도 모른다. 따라서 k를 모른다고 가정하고 최적의 k를 찾는 방법을 학습한다.

 

사실 최적의 k를 찾기 위한 "완벽한" 방법은 없다. 몇가지 도구가 있지만 각자의 장단점이 있을 뿐이다. 여기서는 방법중 하나인 엘보우(elbow)방법에 대해서 공부한다.

 

이너셔(inertia)란 하나의 클러스터에 대해, 각 샘플들과 클러스터 중심과의 거리의 제곱의 합이다.

-> 즉 샘플들이 중심에 가깝게 모여 있으면 이너셔는 작고, 아니면 크다.

-> 또한 클러스터 갯수가 증가하면 당연히 한 클러스터의 샘플수는 줄어드는 경향이 있기 때문에 클러스터의 갯수가 크면 이너셔는 작아진다.

엘보우 방법은 클러스터의 갯수를 차차 늘려가면서 최적의 클러스터 갯수를 찾는 방법이다.

 

상세

클러스터 갯수를 초기값에서부터 학습시키고 점점 증가시켜서 다시 학습하게 되면, 이너셔-클러스터갯수 그래프에서 기울기가 꺾이는 지점이 있다. 다시말해 클러스터의 갯수를 늘림으로써 얻을 수 있는 이너셔 감소율이 떨어지기 시작하는 지점이 있다.

-> 이너셔가 줄어들 수록 당연히 클러스터는 잘 학습된 것이기 때문에 이너셔 감소가 잘 안된다면 클러스터 갯수를 늘릴 때 오히려 효율이 떨어지는 모델이 나올 수 있다.

 

엘보우 방법의 구현

<km_obj> = KMeans(n_clusters = <n>[, random_state = <n>])

km.fit(<train_data>)

<list_for_inertia>.append(km.inertia_)

위 코드를 for문을 이용해서 n_cluster값을 a부터 b까지 대입해 각각 inertia_값을 list에 저장한다. 이너셔 값은 inertia_ 멤버변수에 있다.

 

 

 

 

 

 

관련글 더보기