⊢MachineLearning

비지도학습 : 차원축소 - LDA(Linear Discriminant Analysis)

최 수빈 2025. 3. 17. 19:39

 

LDA (Linear Discriminant Analysis, 선형 판별 분석)

 

차원 축소와 분류를 동시에 수행하는 기법

 

클래스 간 분산을 최대화하고, 클래스 내 분산을 최소화하여 데이터를 변환

저차원 공간에서 데이터의 구조를 유지하면서 분류 성능 향상 가능

 

 

작동 원리

  1. 클래스별 평균 벡터 계산 : 각 클래스의 평균 벡터를 구함
  2. 클래스 내 분산 행렬 계산 : 각 클래스 내부의 데이터 분산 계산
  3. 클래스 간 분산 행렬 계산 : 클래스 평균 벡터 간의 분산을 구함
  4. 고유값 및 고유벡터 계산 : 클래스 내 분산 행렬의 역행렬과 클래스 간 분산 행렬의 곱을 사용하여 고유값과 고유벡터 계산
  5. 선형 판별 축 선택 : 고유값이 큰 순서대로 고유벡터를 정렬하여 주요한 선형 판별 축을 선택
  6. 데이터 변환 : 선택된 판별 축을 사용하여 데이터를 저차원 공간으로 변환

 

*선형 판별 축 선택

고유값이 클수록 해당 선형 판별 축이 클래스 간 분산을 더 많이 설명함

→ 일반적으로, 클래스의 개수 -1 만큼의 선형 판별 축을 선택

 

 

LDA 실습

MNIST 데이터셋을 활용하여 LDA를 적용

 

 

MNIST 데이터셋 로드

from sklearn.datasets import fetch_openml
import pandas as pd

# MNIST 데이터셋 불러오기
mnist = fetch_openml('mnist_784', version=1)

# 데이터와 레이블 분리
X = mnist.data
y = mnist.target

# 데이터 프레임의 첫 5행 출력
print(X.head())
print(y.head())

"""
   pixel1  pixel2  pixel3  pixel4  pixel5  pixel6  pixel7  pixel8  pixel9  \
0       0       0       0       0       0       0       0       0       0   
1       0       0       0       0       0       0       0       0       0   
2       0       0       0       0       0       0       0       0       0   
3       0       0       0       0       0       0       0       0       0   
4       0       0       0       0       0       0       0       0       0   

   pixel10  ...  pixel775  pixel776  pixel777  pixel778  pixel779  pixel780  \
0        0  ...         0         0         0         0         0         0   
1        0  ...         0         0         0         0         0         0   
2        0  ...         0         0         0         0         0         0   
3        0  ...         0         0         0         0         0         0   
4        0  ...         0         0         0         0         0         0   

   pixel781  pixel782  pixel783  pixel784  
0         0         0         0         0  
1         0         0         0         0  
2         0         0         0         0  
3         0         0         0         0  
4         0         0         0         0  

[5 rows x 784 columns]
0    5
1    0
2    4
3    1
4    9
Name: class, dtype: category
Categories (10, object): ['0', '1', '2', '3', ..., '6', '7', '8', '9']
"""

 

 

데이터 표준화

from sklearn.preprocessing import StandardScaler

# 데이터 표준화
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

 

 

 

LDA 수행

 

Scikit-learn의 LinearDiscriminantAnalysis를 사용하여 LDA를 수행

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

# LDA 모델 생성 (클래스의 수 - 1 만큼의 선형 판별 축 선택)
lda = LinearDiscriminantAnalysis(n_components=9)

# LDA 학습 및 변환
X_lda = lda.fit_transform(X_scaled, y)

# 변환된 데이터의 크기 확인
print(X_lda.shape)

"""
(70000, 9)
"""

 

 

LDA 결과 시각화

import matplotlib.pyplot as plt
import seaborn as sns

# 2차원 시각화
plt.figure(figsize=(10, 7))
sns.scatterplot(x=X_lda[:, 0], y=X_lda[:, 1], hue=y, palette='viridis', legend=None)
plt.title('LDA of MNIST Dataset (2D)')
plt.xlabel('LDA Component 1')
plt.ylabel('LDA Component 2')
plt.show()

LDA of MNIST Dataset (2D)