#!/usr/bin/env python3
얼굴이미지에 NMF 적용하기
NMF의 핵심 매개변수는 추출할 성분의 갯수
보통 이 값은 특성의 갯수보다 작음(픽셀하나가 두개의 성분으로 나뉘어 표현될 수 있음)
1. NMF를 사용하여 데이터를 재구성하는데 성분의 갯수가 어떤 영향을 주는지 살펴보기
# library import
from sklearn.datasets import fetch_lfw_people
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import mglearn
# matplotlib 설정
matplotlib.rc('font', family='AppleGothic') # 한글 설정
plt.rcParams['axes.unicode_minus'] = False # 축 -설정
people = fetch_lfw_people(min_faces_per_person=20, resize=0.7, color=False) # 겹치지 않는 최소사람 수, 사이즈비율, 흑백
images_shape = people.images[0].shape # 이미지 한개의 사이즈 저장
counts = np.bincount(people.target) # 갯수 새기
for i, (count, names) in enumerate(zip(counts, people.target_names)): # counts와 people.target_names에서 원소 하나씩 할당하여 인덱스 부여
print('{0:25} {1:3}'.format(names, count), end='\t') # names에서 25자리, count에서 3자리, 끝에 탭할당
if i % 3 == 0: # 3의 배수
print() # 개행
idx = np.zeros(people.target.shape, dtype=np.bool) # False배열 3023개 설정
people_target_unq = np.unique(people.target) # target에서 unique값 할당
for target in people_target_unq: # perploe_target_unq에서 원소 하나씩 target에 할당
idx[np.where(people.target == target)[0][:50]] = 1 # 전체 리스트 3023개에서 target과 일치하는 것의 수가를 50개 까지 True로 변경
x_people = people.data[idx] # 훈련 데이터
y_people = people.target[idx] # 테스트 데이터
# library import
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
scaler = MinMaxScaler()
x_people_scaled = scaler.fit_transform(x_people) # 훈련 데이터를 적용하여 전처리
x_train, x_test, y_train, y_test = \
train_test_split(x_people_scaled, y_people, # 분할할 데이터
stratify=y_people, random_state=0, test_size=0.3) # 그룹화할데이터, 랜덤상태, 테스트 비율
mglearn.plots.plot_nmf_faces(x_train, x_test, images_shape)
plt.gray() # 그림 흑백
plt.show() # 그림 출력
NMF 성분 갯수에 따른 얼굴 이미지의 재구성
변환을 되돌린 결과는 PCA를 사용했을 때와 비슷하지만 품질이 떨어짐
PCA가 재구성 측면에서 최선의 방향을 찾기 때문
NMF는 데이터에 있는 유용한 패턴을 찾는데 활용
2. 비음수 성분 15개로 시각화
# library import , model 생성 , 학습
from sklearn.decomposition import NMF
nmf = NMF(n_components=15, random_state=0)
nmf.fit(x_train)
# 모델 적용
x_train_nmf = nmf.transform(x_train)
x_test_nmf = nmf.transform(x_test)
# 시각화
fig, axes = plt.subplots(3, 5, # axes에 plots객체를 3x5 만큼 할당
subplot_kw={'xticks':(), 'yticks':()}) # subplot 축 없애기
for i, (comp, ax) in enumerate(zip(nmf.components_, axes.ravel())): # nmf.components_, axes.ravel()에서 하나씩 comp와 ax에 인덱스부여
ax.imshow(comp.reshape(images_shape)) # images_shape= (87, 65)
ax.set_title('성분 {}'.format(i)) # subplot 타이틀
plt.gray() # 그림 흑백
plt.show()
얼굴 데이터셋에서 NMF로 찾은 성분 15개
이 성분들은 모두 양수 값이어서 PCA 성분보다 훨씬 더 얼굴 원형처럼 보임
비음수 성분이 특별히 강하게 나타난 이미지 분석(1)
### argsort : 자료를 정렬한 것의 index
idx = np.argsort(x_train_nmf[:, 3])[::-1] # [start : end : stpe] , step=-1 :내림차순
fig, axes = plt.subplots(2, 5, # subplots객체 (2x5) 를 axes에 할당
subplot_kw={'xticks':(), 'yticks':()}) # subplots에 축 없애기
for idx, ax in zip(idx, axes.ravel()): # idx와 aexs.ravel()을 하나씩 idx, ax에 할당
ax.imshow(x_train[idx].reshape(images_shape))
plt.gray() # 그림 흑백
plt.show() # 그림 출력
성분 3의 계수가 큰 얼굴들 10개
비음수 성분이 특별히 강하게 나타난 이미지 분석(2)
idx = np.argsort(x_train_nmf[:, 10])[::-1] # [start : end : stpe] , step=-1 :내림차순
fig, axes = plt.subplots(2, 5, # subplots객체 (2x5) 를 axes에 할당
subplot_kw={'xticks':(), 'yticks':()}) # subplots에 축 없애기
for idx, ax in zip(idx, axes.ravel()): # idx와 aexs.ravel()을 하나씩 idx, ax에 할당
ax.imshow(x_train[idx].reshape(images_shape))
plt.gray() # 그림 흑백
plt.show() # 그림 출력
성분 10의 계수가 큰 얼굴들 10개
성분 3의 계수가 큰 얼굴은 왼쪽으로 돌아가 있고 성분 10의 계수가 큰 얼굴을 왼쪽으로 돌아가 있음을 확인
이런 패턴으로 데이터를 추출
'python 머신러닝 -- 비지도학습 > NMF(비음수 행렬 분해)' 카테고리의 다른 글
NMF(비음수 행렬 분해) (0) | 2018.03.21 |
---|