데이터분석-머신러닝-AI/강의 정리

[혼자 공부하는 머신러닝+딥러닝] 16강. 주성분 분석: 차원 축소 알고리즘 PCA 모델 만들기 - 차원축소 PCA를 다른 알고리즘과 함께 사용하기

bluebamus 2023. 11. 19.

https://www.youtube.com/watch?v=ePqKgBnpcw4&list=PLJN246lAkhQjoU0C4v8FgtbjOIXxSs_4Q&index=23

 

 1. 차원 축소

   - 차원의 정의

   - 데이터가 가진 속성을 특성이라 하고 머신러닝에서는 이 특성을 차원이라고 부른다.

      - 예를 들어 이전 강의에서 사용한 과일 사진의 경우 1개의 샘플이 가로 100, 세로 100 크기의 특성을 가지고 있었으며 하나의 특성은 0~255 사이의 값을 가지고 있었다. 

   - 2차원 배열은 축이 2개이고 3차원 배월은 축이 3개가 있다 한다.

   - 1차원 배열은 벡터라 볼 수 있고 벡터에 있는 원소의 개수를 차원이라 한다.

      - 벡터에서 차원을 이야기할 경우 벡터에 있는 원소의 개수를 의미한다.

      - 2차원 배열 이상에서 차원을 이야기할 경우 축을 의미한다.

 

   - 차원 축소 

   - 비지도학습으로 데이터를 가장 잘 나타내는 일부 특성을 선택하여 전체 데이터의 크기를 줄여준다.

      - 다른 알고리즘과 함께 사용되어 성능을 향상하는 방법을 제공한다.

         - 특성 개수가 많아지면 과대적합되는 문제가 있는데 이를 막아줄 수 있다.

         - 데이터 전체 용량을 줄여주며 이로인해 시각화 하기도 쉬워진다.

      - 축소된 차원의 데이터를 이용해 원본 차원으로 복원할 수 있다.

         - 누락된 데이터로 인해 손실된 이미지로 복원된다. 100% 완벽히 복원되지는 않는다.

      - 대표적으로 주성분 분석(Principal Component Analysis)가 있다.

 

 2. 주성분 분석

   - 첫번째 주성분

      - 일반적으로 데이터의 분산이 잘 되어 있는 그래프에서 분산이 가장 큰 방향을 찾게되면 아래와 같은 선형이 그려진다.

      - 데이터를 가장 많이 퍼져있는 방향이 데이터를 가장 잘 표현할 수 있는 방향이 된다.

 

      - 이 직선의 중심을 원점으로 이동하면 벡터로 표현하기 쉬워진다.

      - 평균을 빼서 두 축의 원점에 맞추고 원점에서 시작하는 벡터를 찾아서 가장 잘 표현한 퍼펙트 벡터를 찾는다. 이것을 주성분이라 한다. 이 주성분을 찾는 것이 주성분 분석이다.

      - 현재 특성은 X1, X2 두개이다. 하지만 주성분을 찾음으로 (2,1)이라는 하나의 특성으로 차원축소를 했다 할 수 있다. 

 

         - 만약 퍼펙트 벡터를 찾은 데이터 분산에서 특정 데이터를 표현하기 위해서는 (x,y) 2차원으로 표현할 수 있다. 하지만 퍼펙트 벡터로부터 수직 데이터를 확인하여 1개의 1차원 데이터로 표현할 수 있다.

 

   - 두번째 주성분

      - 주성분은 원본의 특성 개수만큼 찾을 수 있다.

      - 처음 찾은 주성분으로 부터 수직이고 분산이 그 다음으로 큰 방향을 찾으면 된다.

         - 꼭 수직이어야 하는 이유로 수직이 아닌 방향은 첫번째 주성분의 방향으로 부터 영향을 작게라도 받는다 첫번째 주성분이 표현하지 못하는 분산의 방향을 찾는게 목적이기 때문에 수직인 방향으로 찾는다.

 

 3. PCA 클래스

   - 주성분 분석

   - PCA() : 주성분 분석 클래스

   - n_components : 찾을 주성분의 개수 정의

from sklearn.decomposition import PCA

pca = PCA(n_components=50)
pca.fit(fruits_2d)

 

   - 뽑아낸 주성분(pca)는 .components_에 저장되어 있다.

   - 기존 과일 데이터에서 추출한 주성분이기 때문에 10000개의 특성이 있는 데이터에서 주성분을 찾은 것이다.

print(pca.components_.shape) 
(50, 10000) # 찾은 주성분의 크기는 50개의 주성분과 10000개의 원소인 것을 확인할 수 있다.

 

   - 찾은 주성분을 이미지로 출력하자

      - 원본 데이터셋에서 특정 패턴들을 기준으로 만든 이미지들로 보인다.

draw_fruits(pca.components_.reshape(-1, 100, 100))

 

   - 찾은 주성분을 기반으로 원본 데이터의 차원(특성 개수)를 줄일 수 있다.

      - .transform() : 주성분으로 차원축소를 실행

print(fruits_2d.shape) # 원본 데이터
(300, 10000)

fruits_pca = pca.transform(fruits_2d)
print(fruits_pca.shape)
(300, 50)

 

   - 원본 데이터로 복원

      - 축소된 차원의 데이터를 이용해 다시 원본 데이터로 복원할 수 있다.

         - 차원 축소를 하면서 손실된 데이터는 100% 복원이 안된다 때문에 어느정도 손실된 데이터로 복원된다.

         - inverse_transform() : 주성분을 바탕으로 원본 데이터를 재구성해주는 메소드

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")

 

   - 설명된 분산(explained variance)

      - 주성분이 원본 데이터의 분산을 얼마나 잘 나타내고 있는지 기록한 값을 설명된 분산(explained variance)라 한다.

      - .explained_variance_ratio_ : 각 주성분의 설명된 분산에 대한 비율이 저장되어 있다.

         - 이 변수에 저장된 모든 값을 더하면 주성분이 설명하는 총 분산의 비율을 얻을 수 있다.

print(np.sum(pca.explained_variance_ratio_))
0.9215225564709381

 

      - 변수의 데이터를 그래프로 그려보면 적절한 주성분의 개수를 쉽게 찾을 수 있다.

plt.plot(pca.explained_variance_ratio_)

         - 그래프를 보면 처음 10개 정도의 주성분들이 대부분의 분산을 표현하고 있는 것을 확인할 수 있다.

 

 4. 다른 알고리즘과 함께 사용하기

   - 분류 알고리즘 (로지스틱 회귀)와 함께 사용하기

      - 모델을 만들고 target 값을 설정해준다 (로지스틱 회귀는 target 값을 요구한다)

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
0.6615097999572754

 

      - pca 차원축소한 데이터로 확인해보자

scores = cross_validate(lr, fruits_pca, target)
print(np.mean(scores['test_score']))
print(np.mean(scores['fit_time']))

1.0
0.010721206665039062

 

      - 설명된 분산의 양을 미리 설정할 수 있다. 목표로 하는 분산의 양을 1 이하의 값으로 정의하면 %로 인지하여 해당 목표치만큼의 설명된 분산의 양을 기준으로 주성분 개수를 자동으로 구한다.

pca = PCA(n_components=0.5)
pca.fit(fruits_2d)
print(pca.n_components_)
2  # 50%의 분산의 양을 목표로 하였을 때 2개의 주성분 개수를 구할 수 있다.

fruits_pca = pca.transform(fruits_2d) # 실재 데이터에 반영하여 차원 축소
print(fruits_pca.shape)
(300, 2)

scores = cross_validate(lr, fruits_pca, target) #교차 검정 
print(np.mean(scores['test_score']))
print(np.mean(scores['fit_time']))
0.9933333333333334
0.017629432678222656

 

   - 군집 알고리즘 (k-평균)

      - 비지도 학습이므로 target 값 없이 훈련한다.

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]), array([110,  99,  91], dtype=int64))

for label in range(0, 3):
    draw_fruits(fruits[km.labels_ == label])
    print("\n")

 

 - 데이터 시각화

   - 데이터를 차원축소하면서 얻을 수 있는 장점으로 "시각화"가 있다.

      - 3개 이하의 차원으로 특성을 줄이면 화면에 시각화하기 쉽다.

   - 2개의 특성으로 줄여놓은 fruits_pca를 클러스터 별로 산점도를 그려보면 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()

 

 

 

 

 - reference : 

https://velog.io/@simon919/%ED%98%BC%EA%B3%B5%EB%A8%B8%EC%8B%A0-6-3.-%EC%A3%BC%EC%84%B1%EB%B6%84-%EB%B6%84%EC%84%9D-ledcs7fz

 

[혼공머신] 6-3. 주성분 분석

🚨고객들이 보낸 과일 사진이 너무 많아지면서, 저장공간이 부족해졌다... 업로드된 사진의 용량을 좀 압축시킬 수는 없을까?

velog.io

https://seongyun-dev.tistory.com/4

 

[차원 축소] 주성분 분석 (PCA, Principal Component Analysis)

1. 주성분 분석 (PCA) 주성분 분석은 고차원의 데이터를 분산이 최대로 보존되는 저차원의 축 평면으로 투영시키는 대표적인 차원 축소 방법입니다. 이때 데이터를 투영시킬 수 있는 각 축의 단위

seongyun-dev.tistory.com

 

댓글