[혼자 공부하는 머신러닝+딥러닝] 책의 내용을 정리한 글입니다.
개념
차원
머신러닝에서는 특성을 차원이라고도 부른다.
→ 10,000개의 특성은 10,000개의 차원이라고 볼 수 있다.
- 다차원 배열에서 차원은 배열의 축 개수
- 1차원 배열에서 차원은 원소의 개수
차원 축소
: 원본 데이터의 특성을 적은 수의 새로운 특성으로 변환하는 비지도 학습의 한 종류
- 저장 공간을 줄이고 시각화하기 쉬워짐
- 다른 알고리즘의 성능을 높이고 모델의 훈련 속도도 높일 수 있음
주성분 분석
: 차원 축소 알고리즘의 하나로 데이터에서 가장 분산이 큰 방향을 찾는 방법
- 분산이 가장 큰 방향이란?
- 데이터를 잘 표현하는 어떠한 벡터(크기와 방향을 갖는 물리량을 의미)
- 이 벡터를 주성분이라고 부름
- 원본 데이터를 주성분에 투영하여 새로운 특성을 만들 수 있음
- 일반적으로 주성분은 원본 데이터에 있는 특성 개수보다 작음
설명된 분산
: 주성분 분석에서 주성분이 얼마나 원본 데이터의 분산을 잘 나타내는지 기록한 값
→ 사이킷런의 PCA 클래스는 주성분 개수나 설명된 분산의 비율을 지정하여 주성분 분석을 수행할 수 있다.
코드 작성
주성분 분석으로 차원 축소를 사용하였을 때의 이점을 알아보자.
과일 이미지 데이터 준비
!wget https://bit.ly/fruits_300_data -O fruits_300.npy
import numpy as np
fruits = np.load('fruits_300.npy')
fruits_2d = fruits.reshape(-1, 100*100)
사이킷런의 PCA 클래스를 사용하여 50개의 주성분 확인
from sklearn.decomposition import PCA
pca = PCA(n_components=50)
pca.fit(fruits_2d)
# pca.components_ 배열의 첫 번째 차원은 주성분의 개수, 두 번쨰 차원은 원본 데이터의 특성 개수
print(pca.components_.shape)
# => (50, 10000)
import matplotlib.pyplot as plt
# 이전 장에서 아용했던 이미지 출력 함수
def draw_fruits(arr, ratio=1):
n = len(arr)
rows = int(np.ceil(n/10))
cols = n if rows < 2 else 10
fig, axs = plt.subplots(rows, cols,
figsize=(cols*ratio, rows*ratio), squeeze=False)
for i in range(rows):
for j in range(cols):
if i*10 + j < n:
axs[i, j].imshow(arr[i*10 + j], cmap='gray_r')
axs[i, j].axis('off')
plt.show()
draw_fruits(pca.components_.reshape(-1, 100, 100))
원본 데이터를 찾은 주성분에 투영하여 특성의 개수를 10,000개에서 50개로 줄여보기
print(fruits_2d.shape)
# => (300, 10000)
# transform() 메서드를 사용해 원본 데이터를 각 주성분으로 분해
fruits_pca = pca.transform(fruits_2d)
print(fruits_pca.shape)
# => (300, 50)
축소한 데이터를 다시 원본 데이터로 재구성
fruits_inverse = pca.inverse_transform(fruits_pca)
print(fruits_inverse.shape)
# => (300, 10000)
fruits_reconstruct = fruits_inverse.reshape(-1, 100, 100)
for start in [0, 100, 200]:
draw_fruits(fruits_reconstruct[start:start+100])
print("\n")
주성분이 원본 데이터의 분산을 얼마나 잘 나타내는지 나타내는 설명된 분산 확인
# 각 주성분의 설명된 분산 비율을 모두 더하면 총 분산 비율 확인 가능
print(np.sum(pca.explained_variance_ratio_))
# => 0.9215967336068237
# 설명된 분산 비율 그래프를 보면 적절한 주성분의 개수를 찾는 데 도움이 됨
plt.plot(pca.explained_variance_ratio_)
차원 축소된 데이터를 로지스틱 회귀 모델에 적용
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
target = np.array([0] * 100 + [1] * 100 + [2] * 100)
from sklearn.model_selection import cross_validate
### 원본 데이터를 사용했을 때의 정확도와 훈련 시간
scores = cross_validate(lr, fruits_2d, target)
print(np.mean(scores['test_score']))
print(np.mean(scores['fit_time']))
# => 0.9966666666666667
# => 1.0502480030059815
### 50개의 특성으로 축소한 데이터를 사용했을 때의 정확도와 훈련 시간
scores = cross_validate(lr, fruits_pca, target)
print(np.mean(scores['test_score']))
print(np.mean(scores['fit_time']))
# => 1.0
# => 0.029622936248779298
### 설명된 분산의 50%에 달하는 주성분 개수만큼의 특성 데이터를 사용했을 때의 정확도와 훈련 시간
pca = PCA(n_components=0.5)
pca.fit(fruits_2d)
# 50%를 표현하기 위해 몇개의 주성분을 찾았는지 확인
print(pca.n_components_)
# => 2
fruits_pca = pca.transform(fruits_2d)
scores = cross_validate(lr, fruits_pca, target)
print(np.mean(scores['test_score']))
print(np.mean(scores['fit_time']))
# => 0.9933333333333334
# => 0.02146320343017578
차원 축소된 데이터를 k-평균 알고리즘에 적용
from sklearn.cluster import KMeans
km = KMeans(n_clusters=3, random_state=42)
km.fit(fruits_pca)
# 클러스터별 샘플 개수
print(np.unique(km.labels_, return_counts=True))
# => (array([0, 1, 2], dtype=int32), array([110, 99, 91]))
for label in range(0, 3):
draw_fruits(fruits[km.labels_ == label])
print("\n")
차원 축소 데이터를 통한 시각화
# 3개 이하의 차원을 줄이면 화면에 출력하기 비교적 쉬워진다
for label in range(0,3):
data = fruits_pca[km.labels_ == label]
plt.scatter(data[:,0], data[:,1])
plt.legend(['apple', 'banana', 'pineapple'])
plt.show()
이 장에서 사용된 핵심 패키지와 함수
scikit-learn
- PCA
- 주성분 분석을 수행하는 클래스
- n_components : 주성분의 개수를 지정 (기본값-None, 샘플 개수와 특성 개수 중에 작은 것의 값을 사용)
- random_state : 넘파이 난수 시드 값을 지정
- components_ : 훈련 세트에서 찾은 주성분이 저장됨
- explained_variance_ : 설명된 분산이 저장됨
- explained_variance_ratio_ : 설명된 분산의 비율이 저장됨
- inverse_transform() : transform() 메서드로 차원을 축소시킨 데이터를 다시 원본 차원으로 복원하는 메서드
'Machine Learning' 카테고리의 다른 글
[혼자 공부하는 머신러닝+딥러닝] k-평균 (0) | 2023.05.26 |
---|---|
[혼자 공부하는 머신러닝+딥러닝] 군집 알고리즘 (0) | 2023.05.21 |
[혼자 공부하는 머신러닝+딥러닝] 트리의 앙상블 (0) | 2023.05.14 |
[혼자 공부하는 머신러닝+딥러닝] 교차 검증과 그리드 서치 (0) | 2023.05.09 |
[혼자 공부하는 머신러닝+딥러닝] 결정 트리 (0) | 2023.05.09 |