개요
AI 프로그래밍 수업 시간에 수행한 PCA 와 FDA 실습 및 분석 내용을 기록으로 남긴다.
문제
다음에 대해 주성분 분석(PCA) 및 피셔 판별 분석(FDA)을 수행합니다.
데이터 파일의 MNIST 데이터 집합(클래스 '1', '5', '6'이 있는 MNIST 데이터 집합)에 대해 PCA 와 FDA 을 수행합니다,
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
from google.colab import drive
drive.mount('/content/drive')
train_x = np.load('/content/drive/MyDrive/data_files/mnist_train_images.npy')
train_y = np.load('/content/drive/MyDrive/data_files/mnist_train_labels.npy')
test_x = np.load('/content/drive/MyDrive/data_files/mnist_test_images.npy')
test_y = np.load('/content/drive/MyDrive/data_files/mnist_test_labels.npy')
n_train = train_x.shape[0]
n_test = test_x.shape[0]
print ("The number of training images : {}, shape : {}".format(n_train, train_x.shape))
print ("The number of testing images : {}, shape : {}".format(n_test, test_x.shape))
idx = np.random.randint(train_x.shape[0])
img = train_x[idx].reshape(28,28)
plt.figure(figsize = (6,6))
plt.imshow(img,'gray')
plt.title("Label : {}".format(np.argmax(train_y[idx,:])))
plt.xticks([])
plt.yticks([])
plt.show()
(1) 학습 데이터 세트에 PCA를 적용
### 1. PCA 적용 및 시각화 ###
# PCA 적용 (2개의 주성분)
pca = PCA(n_components=2)
pca.fit(train_x)
train_x_pca = pca.transform(train_x)
test_x_pca = pca.transform(test_x)
# 클래스별 색상 설정
colors = {1: 'red', 5: 'blue', 6: 'green'}
markers = {'train': 'o', 'test': 's'} # 훈련 데이터는 원, 테스트 데이터는 사각형으로 표시
# train_y와 test_y가 원-핫 인코딩되어 있으므로 이를 단일 클래스 값으로 변환
train_y = np.argmax(train_y, axis=1)
test_y = np.argmax(test_y, axis=1)
# 훈련 데이터 시각화
plt.figure(figsize=(10, 8))
for class_label in np.unique(train_y): # train_y에 있는 각 클래스를 순회
plt.scatter(train_x_pca[train_y == class_label, 0],
train_x_pca[train_y == class_label, 1],
c=colors[class_label], label=f'Train Class {class_label}', marker=markers['train'], alpha=0.5)
# 테스트 데이터 시각화
for class_label in np.unique(test_y): # test_y에 있는 각 클래스를 순회
plt.scatter(test_x_pca[test_y == class_label, 0],
test_x_pca[test_y == class_label, 1],
c=colors[class_label], label=f'Test Class {class_label}', marker=markers['test'], alpha=0.5)
# 레이블 추가 및 플롯 설정
plt.xlabel('First principal component')
plt.ylabel('Second principal component')
plt.title('PCA projection of MNIST data (Classes 1, 5, 6)')
plt.legend(loc='best') # 범례 추가
plt.grid(True)
plt.show()
(2) k 차원 표현에서 데이터 재구성하기
# 데이터셋 평균을 구하는 함수
def compute_mean(X):
return np.mean(X, axis=0)
# PCA를 사용하여 k차원으로 복원하는 함수
def pca_reconstruction(X, pca, k):
W_k = pca.components_[:k] # 상위 k개의 주성분 벡터
X_centered = X - pca.mean_ # PCA 학습 시 계산된 평균을 사용해 중심화
X_reconstructed = pca.mean_ + X_centered.dot(W_k.T).dot(W_k) # 복원된 데이터
return X_reconstructed
# 원본 이미지와 복원 이미지를 시각화하는 함수
def plot_reconstructed_images(original, reconstructed, k, n=10):
plt.figure(figsize=(20, 4))
for i in range(n):
# 원본 이미지
plt.subplot(2, n, i + 1)
plt.imshow(original[i].reshape(28, 28), cmap='gray')
plt.title("Original")
plt.axis('off')
# 복원된 이미지
plt.subplot(2, n, i + n + 1)
plt.imshow(reconstructed[i].reshape(28, 28), cmap='gray')
plt.title(f"Recon (k={k})")
plt.axis('off')
plt.show()
# 복원할 차원 수 설정
k_values = [1, 2, 5, 10, 20, 50, 100]
# 테스트 데이터 복원 및 시각화
for k in k_values:
# k차원으로 복원
X_reconstructed = pca_reconstruction(test_x, pca, k)
# 임의의 10개의 샘플 선택
random_indices = np.random.choice(test_x.shape[0], 10, replace=False)
original_images = test_x[random_indices]
reconstructed_images = X_reconstructed[random_indices]
# 원본 및 복원된 이미지 시각화
plot_reconstructed_images(original_images, reconstructed_images, k)
- 작은 k 값 (1, 2, 5)에서는 복원이 상당히 제한적이며, 이미지가 매우 흐릿하게 나타납니다. 숫자의 구체적인 형태는 잘 유지되지 않습니다.
- 중간 k 값 (10, 20)에서는 복원 품질이 크게 향상되며, 숫자의 윤곽과 디테일이 훨씬 더 잘 나타납니다.
- 큰 k 값 (50, 100)에서는 거의 원본 이미지와 구분할 수 없을 정도로 복원 품질이 높습니다.
- 따라서, k 값이 증가함에 따라 복원된 이미지의 품질이 점점 더 좋아지며, k가 50 정도만 되어도 원본 이미지와 거의 차이가 없는 복원이 가능합니다.
(3) 훈련 데이터 세트에 대해 FDA를 수행
# FDA를 적용하여 이차원으로 투영하는 함수
def perform_fda(train_x, train_y, test_x):
lda = LDA(n_components=2) # 2차원으로 투영할 FDA 모델 생성
# 훈련 데이터에 대해 학습
lda.fit(train_x, train_y)
# 훈련 데이터와 테스트 데이터를 각각 투영
train_x_lda = lda.transform(train_x) # 훈련 데이터 변환
test_x_lda = lda.transform(test_x) # 테스트 데이터 변환
return train_x_lda, test_x_lda
# FDA 적용
train_x_lda, test_x_lda = perform_fda(train_x, train_y, test_x)
# 클래스별 색상 설정
colors = {1: 'red', 5: 'blue', 6: 'green'}
markers = {'train': 'o', 'test': 's'} # 훈련 데이터는 원, 테스트 데이터는 사각형으로 표시
# 훈련 데이터 시각화
plt.figure(figsize=(10, 8))
for class_label in np.unique(train_y):
plt.scatter(train_x_lda[train_y == class_label, 0],
train_x_lda[train_y == class_label, 1],
c=colors[class_label], label=f'Train Class {class_label}', marker=markers['train'], alpha=0.5)
# 테스트 데이터 시각화
for class_label in np.unique(test_y):
plt.scatter(test_x_lda[test_y == class_label, 0],
test_x_lda[test_y == class_label, 1],
c=colors[class_label], label=f'Test Class {class_label}', marker=markers['test'], alpha=0.5)
# 레이블 추가 및 플롯 설정
plt.xlabel('First discriminant direction')
plt.ylabel('Second discriminant direction')
plt.title('FDA projection of MNIST data (Classes 1, 5, 6)')
plt.legend(loc='best') # 범례 추가
plt.grid(True)
plt.show()
(4) PCA와 FDA에서 얻은 저차원 표현에 대해 scikit-learn을 사용하여 가장 가까운 이웃(1-NN) 분류를 구현
# 1-NN 분류기를 학습하고 테스트 데이터에 대해 정확도를 평가하는 함수
def evaluate_1nn(train_x, train_y, test_x, test_y):
knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(train_x, train_y) # 훈련 데이터를 사용하여 분류기 학습
predictions = knn.predict(test_x) # 테스트 데이터에 대한 예측
accuracy = accuracy_score(test_y, predictions) # 정확도 계산
return accuracy
# PCA 및 FDA 차원 축소 결과에 따른 1-NN 분류 평가
def evaluate_classification(train_x_pca, test_x_pca, train_x_fda, test_x_fda, train_y, test_y):
# PCA에 대한 1-NN 평가
pca_accuracy = evaluate_1nn(train_x_pca, train_y, test_x_pca, test_y)
# FDA에 대한 1-NN 평가
fda_accuracy = evaluate_1nn(train_x_fda, train_y, test_x_fda, test_y)
return pca_accuracy, fda_accuracy
# 성능 평가 및 결과 시각화
pca_accuracy, fda_accuracy = evaluate_classification(train_x_pca, test_x_pca, train_x_lda, test_x_lda, train_y, test_y)
print(f"PCA with reduced dimensions: Accuracy = {pca_accuracy:.4f}")
print(f"FDA with reduced dimensions: Accuracy = {fda_accuracy:.4f}")
# 정확도 결과 시각화 (단일 비교)
labels = ['PCA', 'FDA']
accuracies = [pca_accuracy, fda_accuracy]
plt.bar(labels, accuracies, color=['blue', 'green'])
plt.ylim(0, 1)
plt.ylabel('Accuracy')
plt.title('1-NN Classification Accuracy (PCA vs FDA)')
plt.show()
PCA with reduced dimensions: Accuracy = 0.8998
FDA with reduced dimensions: Accuracy = 0.9648
- FDA는 클래스 간 분리도를 최대화하기 때문에 1-NN 분류에서 PCA보다 더 높은 성능을 보입니다. PCA는 클래스 정보를 사용하지 않기 때문에 분류 성능이 다소 제한될 수 있습니다.
- FDA의 장점: FDA는 차원이 적더라도 클래스 간의 차이를 잘 반영하여 더 나은 분류 성능을 보일 수 있습니다. 이번 결과에서도 이를 확인할 수 있습니다.
- PCA의 장점: PCA는 클래스 정보 없이 데이터의 전체적인 분산을 최대한 보존하는 방식으로 투영하므로, 주성분을 사용해도 어느 정도의 성능을 유지할 수 있습니다.
- 따라서, 지도 학습이 필요한 상황에서는 FDA가 더 나은 선택이 될 수 있으며, 비지도 학습 환경에서는 PCA가 적절한 선택일 수 있습니다.
'AI > 대학원' 카테고리의 다른 글
RNN 의 Parameter Sharing (1) | 2024.11.21 |
---|---|
Gaussian process 실습 (8) | 2024.11.14 |
VGG16 을 이용한 Transfer Learning 실습 (2) | 2024.11.11 |
도메인에 맞는 AI 지능화 전략 (자율주행 보안) (6) | 2024.11.10 |
한양대학교 인공지능융합대학원 25년도 전기 신입생 모집 (10) | 2024.11.07 |