◾PCA eigenface
- olivetti 데이터
- AT&T와 캠브리지 대학의 공동 연구 데이터
- 얼굴 인식용으로 사용 가능
- 특정 인물의 데이터(10장)만 이용하여 PCA 실습으로 사용
from sklearn.datasets import fetch_olivetti_faces
faces_all = fetch_olivetti_faces()
- 데이터 선택
K = 20
faces = faces_all.images[faces_all.target == K]
faces
![](https://velog.velcdn.com/images%2Fskarb4788%2Fpost%2Fef444a48-996a-45eb-a49c-f539ba8aa7c4%2Fimage.png)
import matplotlib.pyplot as plt
N = 2
M = 5
fig = plt.figure(figsize=(10, 5))
plt.subplots_adjust(top = 1, bottom=0, hspace=0, wspace=0.05)
for n in range(N*M):
ax = fig.add_subplot(N, M, n+1)
ax.imshow(faces[n], cmap=plt.cm.bone)
ax.grid(False)
ax.xaxis.set_ticks([])
ax.yaxis.set_ticks([])
plt.suptitle("Olivetti")
plt.tight_layout()
plt.show()
![](https://velog.velcdn.com/images%2Fskarb4788%2Fpost%2Fea7261c0-de9c-4648-a84b-f35de055a3fd%2Fimage.png)
- PCA 분석(2개의 주성분 선택)
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X = faces_all.data[faces_all.target==K]
W = pca.fit_transform(X)
X_inv = pca.inverse_transform(W)
import matplotlib.pyplot as plt
def draw_faces(faces, N, M, title='', inv = False):
fig = plt.figure(figsize=(10, 5))
plt.subplots_adjust(top = 1, bottom=0, hspace=0, wspace=0.05)
for n in range(N*M):
ax = fig.add_subplot(N, M, n+1)
if inv == False:
ax.imshow(faces[n], cmap=plt.cm.bone)
else:
ax.imshow(faces[n].reshape(64, 64), cmap=plt.cm.bone)
ax.grid(False)
ax.xaxis.set_ticks([])
ax.yaxis.set_ticks([])
plt.suptitle(title)
plt.tight_layout()
plt.show()
draw_faces(X_inv, 2, 5, 'PCA result', True)
![](https://velog.velcdn.com/images%2Fskarb4788%2Fpost%2F6f140017-e236-4d2d-816d-68d285c9664d%2Fimage.png)
- 원점과 두 개의 eigen face
- 10장의 사진은 아래 3장으로 모두 표현할 수 있다.
face_mean = pca.mean_.reshape(64, 64)
face_p1 = pca.components_[0].reshape(64, 64)
face_p2 = pca.components_[1].reshape(64, 64)
plt.figure(figsize=(12, 7))
plt.subplot(131)
plt.imshow(face_mean, cmap=plt.cm.bone)
plt.grid(False); plt.xticks([]); plt.yticks([]); plt.title('mean')
plt.subplot(132)
plt.imshow(face_p1, cmap=plt.cm.bone)
plt.grid(False); plt.xticks([]); plt.yticks([]); plt.title('face_p1')
plt.subplot(133)
plt.imshow(face_p2, cmap=plt.cm.bone)
plt.grid(False); plt.xticks([]); plt.yticks([]); plt.title('face_p2')
plt.show()
![](https://velog.velcdn.com/images%2Fskarb4788%2Fpost%2F227f55ef-8dbb-4a01-a763-8e6b95716573%2Fimage.png)
- 가중치 선정
import numpy as np
N = 2
M = 5
w = np.linspace(-5, 10, N*M)
w
![](https://velog.velcdn.com/images%2Fskarb4788%2Fpost%2F7606ec68-ef84-4db2-8bfa-dea4a55a8d69%2Fimage.png)
- 첫 번째 성분 변화
fig = plt.figure(figsize=(10, 5))
plt.subplots_adjust(top=1, bottom=0, hspace=0, wspace=0.05)
for n in range(N*M):
ax = fig.add_subplot(N, M, n+1)
ax.imshow(face_mean + w[n] * face_p1, cmap=plt.cm.bone)
plt.grid(False); plt.xticks([]); plt.yticks([]);
plt.title('Weight :' + str(round(w[n])))
plt.tight_layout()
plt.show()
![](https://velog.velcdn.com/images%2Fskarb4788%2Fpost%2F160c3824-ce39-4899-9bd1-2d2344c3c7ac%2Fimage.png)
- 두 번째 성분 변화
fig = plt.figure(figsize=(10, 5))
plt.subplots_adjust(top=1, bottom=0, hspace=0, wspace=0.05)
for n in range(N*M):
ax = fig.add_subplot(N, M, n+1)
ax.imshow(face_mean + w[n] * face_p2, cmap=plt.cm.bone)
plt.grid(False); plt.xticks([]); plt.yticks([]);
plt.title('Weight :' + str(round(w[n])))
plt.tight_layout()
plt.show()
![](https://velog.velcdn.com/images%2Fskarb4788%2Fpost%2F1669bd7b-e3c1-4465-9955-f8a5043b3a79%2Fimage.png)
- 두 개의 성분 표현
nx, ny = (5, 5)
x = np.linspace(-5, 8, nx)
y = np.linspace(-5, 8, ny)
w1, w2 = np.meshgrid(x, y)
w1, w2
![](https://velog.velcdn.com/images%2Fskarb4788%2Fpost%2Fc107b7dd-8cea-42dd-b442-59c7bf58a12c%2Fimage.png)
w1.shape
![](https://velog.velcdn.com/images%2Fskarb4788%2Fpost%2Fd334612a-3f46-414c-bbfb-55dbb1f38c01%2Fimage.png)
w1 = w1.reshape(-1, )
w2 = w2.reshape(-1, )
w1.shape
![](https://velog.velcdn.com/images%2Fskarb4788%2Fpost%2F101a7062-817f-4e3f-832b-0ea818c2137f%2Fimage.png)
fig = plt.figure(figsize=(12, 10))
plt.subplots_adjust(top=1, bottom=0, hspace=0, wspace=0.05)
N = 5
M = 5
for n in range(N*M):
ax = fig.add_subplot(N, M, n+1)
ax.imshow(face_mean + w1[n] * face_p1 + w2[n] * face_p2, cmap=plt.cm.bone)
plt.grid(False); plt.xticks([]); plt.yticks([]);
plt.title('Weight :' + str(round(w1[n], 1)) + ', ' + str(round(w2[n], 1)))
plt.show()
![](https://velog.velcdn.com/images%2Fskarb4788%2Fpost%2Fa71bd336-3463-4be9-940f-7843c307823f%2Fimage.png)