#!/usr/bin/env python3


face dataset으로 Agglomerative Algorithm 비교

1. face data load

# library import

from sklearn.decomposition import PCA, NMF

from sklearn.preprocessing import StandardScaler, MinMaxScaler

from sklearn.datasets import fetch_lfw_people

from sklearn.model_selection import train_test_split

from sklearn.cluster import DBSCAN, KMeans, AgglomerativeClustering

import numpy as np

import matplotlib.pyplot as plt

import matplotlib


# matplotlib 설정

matplotlib.rc('font', family='AppleGothic'# 한글출력

plt.rcParams['axes.unicode_minus'] = False # 축 -


# dataset

people = fetch_lfw_people(min_faces_per_person=20, resize=0.7, color=False) 

people_image = people.images[0].shape 


# 빈도수 확인

counts = np.bincount(people.target)


for i, (count, name) in enumerate(zip(counts, people.target_names)):

    print('{0:12} {1:3}'.format(count, name), end='\t')

    if i%3 == 0:

        print()


# 특성의수를 50개까지

idx = np.zeros(people.target.shape, dtype=np.bool)

for target in np.unique(people.target):

    idx[np.where(people.target == target)[0][:50]] = 1


# 데이터 분할

x_people = people.data[idx]

y_people = people.target[idx]


# preprocessing

scaler = MinMaxScaler()

x_people_scaled = scaler.fit_transform(x_people) # 전처리 메소드로 원래데이터 적용




2 . PCA와 NMF를 이용하여 DBSCAN


# PCA 주성분 분석

pca = PCA(n_components=100, whiten=True, random_state=0) 

pca.fit_transform(x_people_scaled) # 모델 fitting

x_pca = pca.transform(x_people_scaled) # 적용한 모델을 원래 데이터에 적용


# NMF 분석

nmf = NMF(n_components=100, random_state=0)

nmf.fit_transform(x_people_scaled) # 모델 fitting

x_nmf = nmf.transform(x_people_scaled) # 적용한 모델을 원래 데이터에 적용


# DBSCAN Agglomerative Algorithm

dbscan = DBSCAN() 

labels_pca = dbscan.fit_predict(x_pca) # pca를 군집화

labels_nmf = dbscan.fit_predict(x_nmf) # nmf를 군집화


print('\n레이블 종류: \npca: {}\nnmf: {}'.format(np.unique(labels_pca), np.unique(labels_nmf))) # [-1], 

### PCA, NMF 모두 레이블이 -1뿐임 ==> DBSCAN에 의해 noise point로 처리

### solution:

### 1. eps값을 크게 ==> 데이터 point의 이웃의수 증가

### 2. min_samples 값을 작게 ==> cluster에 모을 point 수를 감소



3. 알맞은 DBSCAN값 찾기

### 알맞은 eps값 확인 (-1, 0)

for eps in [0.5, 0.7, 0.9, 1, 5, 9, 15, 17]: # eps 목록

    dbscan = DBSCAN(min_samples=3, eps=eps)

    labels_pca = dbscan.fit_predict(x_pca)

    labels_nmf = dbscan.fit_predict(x_nmf)

    print('pca ==> n_samples: {}, eps: {:.3f} - {}'.format(3, eps, np.unique(labels_pca)))

    print('nmf ==> n_samples: {}, eps: {:.3f} - {}\n'.format(3, eps, np.unique(labels_nmf)))


# DBSCAN -- pca

dbscan = DBSCAN(min_samples=3, eps=15)

labels_pca = dbscan.fit_predict(x_pca)


# DBSCAN -- NMF

dbscan = DBSCAN(min_samples=3, eps=1)

labels_nmf = dbscan.fit_predict(x_nmf)


print('레이블 종류: \npca: {}\nnmf: {}'.format(np.unique(labels_pca), np.unique(labels_nmf))) # (-1, 0)

pca_count = np.bincount(labels_pca + 1) # bincount는 음수는 표현할 수없으니 1을 더함

nmf_count = np.bincount(labels_nmf + 1)


print('클러스터별 포인트 수:\npca: {}\nnmf: {}'.format(pca_count, nmf_count))


### visualization

noise_pca = x_people[labels_pca == -1] # noise 값만 추출

noise_nmf = x_people[labels_nmf == -1]


fig, axes = plt.subplots(3, 9,

                        subplot_kw={'xticks':(), 'yticks':()},

                        gridspec_kw={'hspace':0.5})


for image, ax in zip(noise_pca, axes.ravel()):

    ax.imshow(image.reshape(people_image))

plt.gray()

plt.show()

face dataset에서 DBSCAN이 noise point로 레이블한 sample(PCA)


fig, axes = plt.subplots(3, 9,

                        subplot_kw={'xticks':(), 'yticks':()},

                        gridspec_kw={'hspace':0.5})


for image, ax in zip(noise_nmf, axes.ravel()):

    ax.imshow(image.reshape(people_image))

plt.gray()

plt.show()

face dataset에서 DBSCAN이 noise point로 레이블한 sample(NMF)


face image에서 무작위로 선택한 이미지와 비교해보면 대부분 얼굴이 일부 가려져 있거나 각도가 이상, 혹은 너무 가까이거나 너무 멀리 있는 경우임


+ Recent posts