본문 바로가기

컴퓨터/머신러닝

[혼자 공부하는 머신러닝] 6. 비지도 학습

비지도 학습

훈련 세트를 타깃이 없는 데이터를 통해 학습하는 것이다.

대표적으로 군집(clustering), 시각화와 차원축소(visualization & dimensionality reduce), 연관 규칙 학습(association rule learning)이 있다.

군집 알고리즘

과일 데이터를 사용해서 군집 알고리즘을 실험해본다.

과일 데이터는 아래의 코드를 통해서 불러올 수 있고 해당하는 과일에 대한 이미지는 아래와 같다.

이때 cmap을 gray_r로 설정해야 픽셀의 값이 없는 외곽을 흰색으로 설정되고 내부의 이미지 데이터는 흑백이미지로 잘 나오게 된다.

!wget https://bit.ly/fruits_300_data -O fruits_300.npy
fruits = np.load('fruits_300.npy')
fig, axs = plt.subplots(1, 2)
axs[0].imshow(fruits[100], cmap='gray_r')
axs[1].imshow(fruits[200], cmap='gray_r')
plt.show()

 

위 데이터를 히스토그램을 통해 픽셀 전체에 평균적인 분포가 어떻게 되어있는지 살펴보면 아래와 같다.

이를 통해서 바나나의 경우 픽셀값이 비어있는 부분이 많아 쉽게 구분할 수 있는 것으로 보이고, 파인애플과 사과는 히스토그램을 통해서는 구분할 수 없는것으로 보인다.

 

이를 구분하기 위해서 각각의 픽셀별로 이미지가 어떻게 분포하고 있는지 찾아서 해당하는 샘플의 평균값 이미지를 통해 차이가 적은 샘플을 해당 군집으로 분류하는 방법을 사용할 수 있다.

 

abs_diff = np.abs(fruits - apple_mean)
abs_mean = np.mean(abs_diff, axis=(1,2))
apple_index = np.argsort(abs_mean)[:100]
fig, axs = plt.subplots(5, 5, figsize=(5,5))
for i in range(5):
    for j in range(5):
        axs[i, j].imshow(fruits[apple_index[i*5 + j]], cmap='gray_r')
        axs[i, j].axis('off')
plt.show()

위 코드를 통해서 사과의 픽셀별로 평균값을 찾아 해당 픽셀과 차이가 적은 것을 사과로 분류하여 분류가 잘 된 것을 볼 수 있다.

 

k-mean

k-mean에서는 찾아야할 클러스터 개수를 k라고 할 때 먼저 랜덤하게 k개의 샘플을 클러스터의 중심으로 가정한다.

그 후 모든 샘플을 k개의 클러스터중 하나로 레이블링 하는데 이때 데이터에 가장 가까운 클러스터값으로 레이블링 한다.

모든 샘플이 레이블링 되었으면 각 클러스터의 평균을 구해 그 점을 다시 클러스터의 중심으로하고 위의 과정을 반복한다.

이렇게 하면 시행을 반복할수록 샘플과 가장 가까운 클러스터의 중심 사이의 평균 제곱 거리는 항상 감소함으로 어느 순간에는 수렴하게 된다.

하지만 초기값이 랜덤으로 결정되기 때문에 수렴한 값이 항상 최적의 답인 것은 확실할 수 없다.

최적의 클러스터 개수 찾기

모든 경우를 시도를 해서 가장 오차가 작은 모델고르면 좋을 것 같지만 클러스터의 수가 많으면 하나의 클러스터임에도 2개로 나누어 분류하여 오차는 줄어들지만 좋지 않은 모델이 될 수가 있다.
그래서 무작정 많은 클러스터를 선택하는 것은 좋지 않고 클러스터의 개수를 늘리면서 오차의 감소 속도가 바뀌는 변곡점에 해당하는 점을 찾아 이 값을 최적값으로 하는 것이 좋다.

변곡점을 찾아 적절한 클러스터 개수를 정하는 것을 엘보우 방법이라고 한다.

inertia = []
for k in range(2, 7):
    km = KMeans(n_clusters=k, n_init='auto', random_state=42)
    km.fit(fruits_2d)
    inertia.append(km.inertia_)

plt.plot(range(2, 7), inertia)
plt.xlabel('k')
plt.ylabel('inertia')
plt.show()

이 방법을 통해서 위의 과일 데이터의 경우 최적의 클러스터 갯수는 3개임을 볼 수 있다.

 

k-mean 알고리즘은 클러스터 중심과 클러스터에 속한 샘플 사이의 거리를 젤 수 있는데 이 거리의 제곱의 합을 이너셔라고 한다.

일반적으로 클러스터의 개수가 늘어나면 이너셔가 줄기 때문에 클러스터 개수에 따른 이너셔의 변화를 통해 적절한 클러스터 수를 유추할 수 있다.


더 정확한 방법을 사용하려면 실루엣 점수를 활용하여 구하면 된다.
실루엣 점수는 모든 샘플에 대한 실루엣 계수의 평균으로 실루엣 계수는 다음과 같다. $\frac{b-a}{\max(a, b)}$
이때 a는 동일한 클러스터에 있는 다른 샘플까지 평균거리이고 b는 자신이 속한 클러스터를 제외한 가장 가까운 클러스터까지 거리의 평균이다.
실루엣 점수값이 1에 가까우면 자신의 클러스터 안에 잘 속해 있다는 것이고, 0이면 클러스터의 경계에 -1이면 다른 클러스터에 할당되었다는 의미이다.
점수를 구한 후에 실루엣 다이어그램으로 각 클러스터 별 샘플의 수와 실루엣 계수를 비교하여 적절한 클러스터 수를 정하면 된다.


k-mean의 단점은 최적의 수렴을 찾기 위해 많이 반복해야 하고, 클러스터의 개수도 찾아야 한다.
그리고 데이터의 분포가 클러스터별로 원형이 아니면 잘 작동하지 않는 단점이 있다.

주성분 분석(PCA)

주성분 분석은 데이터에 가장 가까운 초평면을 정의한 다음에 데이터들을 이 평면에 투영시키는 방식을 사용한다.

투영을 할때는 분산이 최대로 보존되는 축을 선택하는 것이 정보가 가장 적게 손실되어 좋다.

즉, 원본 데이터와 투영된 데이터 사이의 평균 제곱 거리가 최소화 되는 축을 찾는 것이 중요하다.

  • PCA의 훈련 방법
    1. 먼저 훈련 세트의 분산이 최대인 축을 찾는다. 이때 훈련세트의 주성분을 찾는 방법은 특잇값 분해를 이용해 표준 행렬 분해기술로 찾으면 된다.

    2. 첫 번째 축에 직교하고 남은 분산을 최대한 보존하는 두 번째 축을 찾는다.

    3. 이전의 축에 직교하는 다음 축을 데이터셋에 있는 차원의 수 만큼 반복하여 찾는다.

    4. 주성분을 모두 찾으면 처음 d개의 주성분으로 구성된 초평면에 투영하여 데이터셋의 차원을d차원으로 축소한다.

적절한 차원 수 선택하기

축소할 차원의 수를 임의로 정하기 보다는 충분한 분산이 될 때까지 더해야 할 차원의 수를 선택하는 것 좋다.

혹은 설명된 분산을 차원수에 대한 함수로 표현하여 분산의 빠른 성장이 멈추는 변곡점을 택하면 된다.

물론 모델을 훈련하는 것이 아니라 시각화를 위해 차원을 축소하는 경우는 2개나 3개의 차원으로 줄이는 것이 좋다.

압축을 하고 나면 데이터셋의 크기가 줄어들어 알고리즘의 속도를 크게 높일 수 있다.

 

그리고 완벽하게는 아니지만 원본 데이터와 매우 유사하게 다시 복원도 할 수 있는데 이때 발생하는 오차를 재구성 오차라고 한다.

 

PCA의 문제점은 svd알고리즘을 실행하기 위해 전체 훈련 세트를 메모리에 올려야 한다는 것이다.

이러한 문제를 해결하기 위해 점진적PCA(IPCA)알고리즘을 사용하면 된다.

IPCA는 훈련 세트를 미니배치로 나눈 뒤 알고리즘에 하나씩 주입하는데, 이렇게 하면 새로운 데이터가 준비되는대로 실시간으로 PCA를 적용할 수 있게 되는 장점이 있다.