#!/usr/bin/env python3
1. PCA -- eigen face
PCA는 원본 데이터 표현보다 분석하기에 더 적합한 표현을 찾을 수 있으리란 생각에서 출발
이미지는 RGB의 강도가 기록된 픽셀로 구성
PCA를 이용하여 LFW(Labeled Faces in the Wild) 데이터셋의 이미지에서 특성을 추출
# library import
from sklearn.datasets import fetch_lfw_people # fetch_lfw_people library
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
# 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) # 추출된 사진의 서로 다른 얼굴의 수, 사진 비율, 흑백여부
image_shape = people.images[0].shape # people객체 image의 첫번째 원소의 모양
print('people.images의 형태 \n{}'.format(people.images.shape)) # people객체의 image 형태: (3023, 87, 65)
print('class 갯수 \n{}'.format(len(people.target_names))) # people객체의 class 갯수, 62
fig, axes = plt.subplots(2, 5, # figure객체와 2x5의 plot객체를 각각 할당
subplot_kw={'xticks': (), 'yticks': ()}) # subplot의 축 설정; x축 눈굼없게, y축 눈금없게
# axes.ravel() : 리스트를 1차원으로
for target, image, ax in zip(people.target, people.images, axes.ravel()): # people.target, people.images, axes.ravel()에서 하나씩 원소 할당
ax.imshow(image) # imshow로 그림 출력
ax.set_title(people.target_names[target]) # 각 subplot의 타이틀
plt.gray() # 그림 흑백
plt.show() # 그래프 출력
LFW 데이터셋에 있는 이미지의 샘플
1 -1 people 객체 분석
# 각 target이 나타난 횟수 계산
counts = np.bincount(people.target) # people.target의 빈도 계산
# target별 이름과 횟수 출력
### enumerate() : 각 원소에 인덱스 부여
### print('{0:25}, {1:3}').format(var1, var2): 첫번째 {}에 var1과 25자리까지, 두번째{}에 var2와 3자리를 부여
### print({0!s}.format(var1)): print문에 전달된 형식이 숫자라도 문자로 처리
print('frequency')
for i, (count, name) in enumerate(zip(counts, people.target_names)):
print('{0:25} {1:3}'.format(name, count), end= '\t') # name에서 25자리, count에서 3자리, 끝은 탭
if (i + 1) % 3 == 0: # 3의 배수이면, 즉 4번째 원소부터
print() # 개행처리
# Geoge W Bush와 Colin Powell의 이미지가 많음을 확인
### 데이터셋의 편중을 막기 위해 50개의 이미지만 선택
mask = np.zeros(people.target.shape, dtype=np.bool) # 3023개의 boolean타입 False 생성
people_unique = np.unique(people.target) # 중복된 값 제외
for target in people_unique: # 중복을 제거한 target리스트에서 한개의 원소 선택
# people.target(3023개의 리스트)중 선택된 원소와 같은 것만 출력 ==> [0] 리스트의 원소로 접근 ==> False의 갯수 50개까지 출력
# 이 논리 값을 mask의 인덱스로 사용 후 True로 변환
x_people = people.data[mask] # 훈련 데이터 생성
y_people = people.target[mask] # 테스트 데이터 생성
# 전처리 메소드 import
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
x_people_scaled = scaler.fit_transform(x_people) # 전처리 메소드 적용
# 머신 러닝 library import
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
# 전처리한 데이터를 분할
x_train, x_test, y_train, y_test = \
train_test_split(x_people_scaled, y_people, # 분할할 데이터
stratify=y_people, random_state=0) # 그룹화할 데이터, 랜덤상태
# 머신 러닝 라이브러리 import
knn = KNeighborsClassifier(n_neighbors=1) # 이웃의 수
knn.fit(x_train, y_train) # 모델 학습
print('knn.score(x_test, y_test) \n최근접이웃의 일반화 세트 점수: {:.3f}'.format(
knn.score(x_test, y_test))) # 0.248
정확도가 24.8%, 무작위로 분류하는 정확도는 1/62 = 1.6%
얼굴의 유사도를 측정하기 위해 원본 픽셀 공간에서 거리를 계산하는 것은 비효율적
각 픽셀의 회색톤 값을 다른 이미지에서 동일한 위치에 있는 픽셀 값과 비교. 이런 방식은 사람이 얼굴 이미지를 인식하는 것과는 많이 다르고, 픽셀을 있는 그대로 비교하는 방식으로는 얼굴의 특징을 잡아내기 어려움
2. PCA whitening 분석
픽셀을 비교할 때 얼굴 위치가 한 픽셀만 오른쪽으로 이동해도 큰 차이를 만들어 완전히 다른얼굴로 인식
주성분으로 변환하여 거리를 계산하여 정확도를 높이는 방법을 사용, PCA whitening 옵션을 사용하여 주성분의 스케일이 같아지도록 조정 ==> whitening 옵션 없이 변환 후 StandardScaler를 적용하는 것과 같음
# library import
import mglearn
mglearn.plots.plot_pca_whitening()
plt.show()
whitening옵션을 사용한 PCA 데이터 변환
데이터가 회전하는 것뿐만 아니라 스케일도 조정되어 그래프가 원 모양으로 바뀜
2-1. PCA 머신 러닝
# library import
from sklearn.decomposition import PCA
# PCA 모델 생성 및 적용
pca = PCA(n_components=100, whiten=True, random_state=0) # 주성분 갯수, whitening option, 랜덤상태
pca.fit(x_train) # PCA 학습
x_train_pca = pca.transform(x_train) # PCA를 데이터에 적용
x_test_pca = pca.transform(x_test)
# PCA를 적용한 데이터 형태
print('x_train_pca.shape \ntrain형태:{}'.format(x_train_pca.shape)) # (1547, 100)
print('x_test_pca.shape \ntest형태:{}'.format(x_test_pca.shape)) # (516, 100)
# 머신 러닝 모델 생성 및 학습
knn = KNeighborsClassifier(n_neighbors=1) # 이웃의 수
knn.fit(x_train_pca, y_train) # 모델 학습
print('테스트 세트 정확도: \n{:.3f}'.format(knn.score(x_test_pca, y_test))) # 0.314
모델의 정확도가 23%에서 31%로 상승
이미지 데이터일 경우엔 계산한 주성분을 쉽게 시각화 가능
주성분이 나타내는 것은 입력 데이터 공간에서의 어떤 방향임을 기억
입력 차원이 87 x 65픽셀의 흑백 이미지이고 따라서 주성분또한 87 x 65
print('pca.components_.shape \n{}'.format(pca.components_.shape)) # (100, 5655)
fig, axes = plt.subplots(3, 5, # subplot 3x5를 axes에 할당
subplot_kw={'xticks': (), 'yticks': ()}) # subplot 축 설정
for i, (comp, ax) in enumerate(zip(pca.components_, axes.ravel())): # pca.components_와 axes.ravel()을 하나씩 순서대로 할당한 후 인덱스 부여
ax.imshow(comp.reshape(image_shape)) # image_shape= (87, 65)
ax.set_title('pricipal component {}'.format(i+1)) # image title
plt.gray() # 사진 흑백
plt.show() # 사진 출력
얼굴 데이터셋의 pricipal component중 처음 15개
첫 번째 주성분은 얼굴과 배경의 명암차이를 기록한 것으로 추정
두번째 주성분은 오른쪽과 왼쪽 조명의 차이를 담고 있는 것으로 보임
이런 방식이 원본 픽셀 값을 사용하는 것보다 더 의미 있지만, 사람이 얼굴을 인식하는 방식과는 거리가 멈
알고리즘이 데이터를 해석하는 방식은 사람의 방식과는 상당히 다름
PCA 모델을 이해하기 위해 몇개의 주성분을 사용해 원본 데이터를 재구성
몇 개의 주성분으로 데이터를 줄이고 원래 공간으로 되돌릴 수 있음
원래 특성 공간으로 되돌리는 작업은 inverse_transform 메소드를 사용
mglearn.plots.plot_pca_faces(x_train, x_test, image_shape) # 훈련데이터, 테스트데이터, 이미지크기(87x65)
plt.gray() # 그림 흑백
plt.show() # 그림 출력
주성분 갯수에 따른 세 얼굴 이미지의 재구성
'python 머신러닝 -- 비지도학습 > PCA(주성분 분석)' 카테고리의 다른 글
PCA (0) | 2018.03.19 |
---|