[2022_하계_모각코] 5회차(08/09)
5회 차 목표
차원축소 학습하기
1. 차원 축소(Dimension Reduction) 개요
차원축소는 매우 많은 피처로 구성된 다차원 데이터 세트의 차원을 축소해 새로운 차원의 데이터 세트를 생성하는 것이다. 일반적으로 차원이 증가할수록 데이터 포인트 간의 거리가 기하급수적으로 멀어지게 되고, 희소한 구조를 가지게 된다.
수백 개 이상의 피처로 구성된 데이터 세트의 경우 상대적으로 적은 차원에서 학습된 모델보다 예측 신뢰도가 떨어진다. 또한 피처가 많을 경우 개별 피처간에 상관관계가 높을 가능성이 크다.
이렇게 매우 많은 다차원의 피처를 차원 축소해 피처 수를 줄이면 더 직관적으로 데이터를 해석할 수 있다. 수십 개 이상의 피처가 있는 데이터의 경우 이를 시각적으로 표현해 데이터의 특성을 파악하기는 불가능하다. 이 경우 3차원 이하의 차원 축소를 통해 시각적으로 데이터를 압축해 표현할 수 있다. 차원 축소를 할 경우 학습 데이터의 크기가 줄어들어서 학습에 필요한 처리 능력도 줄일 수 있다.
차원 축소 | 피처 선택 | 특정 피처에 종속성이 강한 불필요한 피처는 아예 제거하고, 데이터의 특징을 잘 나타내는 주요 피처만 선택하는 것 |
피처 추출 | 기존 피처를 저차원의 중요 피처로 압축해서 추출하는 것 |
2. PCA(Principal Component Analysis)
PCA 개요
PCA(principal component analysis)는 가장 대표적인 차원 축소 기법이다. PCA는 여러 변수 간에 존재하는 상관관계를 이용해 이를 대표하는 주성분을 추출해 차원을 축소하는 기번이다. PCA로 차원을 축소할 떄는 기존 데이터의 정보 유실이 최소화되는 것이 당연하다. 이를 위해서 PCA는 가장 높은 분산을 가지는 데이터의 축을 찾아 이 축으로 차원을 축소하는데 이것이 PCA의 주성분이 된다.
PCA는 제일 먼저 가장 큰 데이터 변동성을 기반으로 첫 번째 벡터 축을 생성하고, 두 번째 축은 이 벡터 축에 직각이 되는 벡터를 축으로 한다. 세 번째 축은 다시 두 번째 축과 직각이 되는 벡터를 설정하는 방식으로 축을 생성한다. 이렇게 생성된 벡터 축에 원본 데이터를 투영하면 벡터 축의 개수만큼의 차원으로 원본 데이터가 차원 축소된다.
입력 데이터의 공분산 행렬이 고유벡터와 고유값으로 분해될 수 있으며, 이렇게 분해된 고유벡터를 이용해 입력 데이터를 선형 변환하는 방식이 PCA라는 것이다
- 입력 데이터 세트의 공분산 행렬을 생성한다.
- 공분산 행렬의 고유 벡터와 고유값을 계산한다.
- 고유값이 가장 큰 순으로 K개(PCA 변환 차수만큼)만큼 고유 벡터를 추출한다.
- 고유값이 가장 큰 순으로 추출된 고유 벡터를 이용해 새롭게 입력 데이터를 변환한다.
from sklearn.datasets import load_iris
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
iris=load_iris()
#넘파이 데이터 세트를 판다스 dataframe으로 변환
columns=['sepal_length','sepal_width','petal_length','petal_width']
df=pd.DataFrame(iris.data,columns=columns)
df['target']=iris.target
df.head(3)
각 품종에 따라 원본 붓꽃 데이터 세트가 어떻게 분포되어 있는지 2차원으로 시각화해보자. 2차원으로 표현하므로 두 개의 속성인 sepal length와 sepal width를 X축, Y축으로 해 품종 데이터 분포를 나타낸다.
#setosa는 세모, versicolor는 네머, virginica는 동그라미로 표현
markers=['^','s','o']
#setosa의 target값은 0,versicolor는 1,virginica는 2. 각 target별로 다른 모양으로 산점도로 표시
for i,marker in enumerate(markers):
x_axis_data=df[df['target']==i]['sepal_length']
y_axis_data=df[df['target']==i]['sepal_width']
plt.scatter(x_axis_data,y_axis_data,marker=marker,label=iris.target_names[i])
plt.legend()
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.show()
setosa 품종의 경우 sepal width가 3.0보다 크고, sepal length가 6.0 이하인 곳에 일정하게 분포되어있다. versicolor와 virginica의 경우 sepal width와 sepal length 조건만으로는 분류가 어려운 복잡한 조건임을 알 수 있다. 이제 PCA로 4개의 속성을 2개로 압축한 뒤에 앞의 예제에 비슷하게 3개의 PCA 속성으로 붓꽃 데이터의 품종 분포를 2차원으로 시각화해보자.
개별 속성을 함께 스케일링
from sklearn.preprocessing import StandardScaler
#target 값을 제외한 제외한 모든 속성 값을 standardscaler를 이용해 표준 정규 분포를 가지는 값들로 변환
iris_scaled=StandardScaler().fit_transform(df.iloc[:,:-1])
스케일링이 적용된 데이터 세트에 PCA를 적용해 4차원의 붓꽃 데이터를 2차원 PCA 데이터로 변환해보자.
from sklearn.decomposition import PCA
from sklearn.decomposition import PCA
pca=PCA(n_components=2)
pca.fit(iris_scaled)
iris_pca=pca.transform(iris_scaled)
print(df.shape)
(150, 5)
PCA 객체의 transform()메서드를 호출해 원본 데이터 세트를 (150,2)의 데이터 세트로 iris_pca 객체변수로 반환했다. iris_pca는 변환된 PCA 데이터 세트를 150*2 넘파이 행렬로 가지고 있다. 이를 Dataframe으로 변환한 뒤 데이터 값을 확인해보자.
#PCA변환된 데이터의 칼럼명을 각각 pca_component_1,pca_component_2로 명명
pca_columns=['pca_component_1','pca_component_2']
irisdf_pca=pd.DataFrame(iris_pca,columns=pca_columns)
irisdf_pca['target']=iris.target
irisdf_pca.head(3)
#setosa를 세모, versicolor를 네모, virginica를 동그라미로 표시
markers=['^','s','o']
#pca_component_1을 x축, pc_component_2를 y축으로 scatter plot수행
for i,marker in enumerate(markers):
x_axis_data=irisdf_pca[irisdf_pca['target']==i]['pca_component_1']
y_axis_data=irisdf_pca[irisdf_pca['target']==i]['pca_component_2']
plt.scatter(x_axis_data,y_axis_data,marker=marker,label=iris.target_names)
plt.legend()
plt.xlabel('pca_component_1')
plt.ylabel('pca_component_2')
plt.show()
PCA로 변환한 후에도 pca_component_1축을 기반으로 setosa품종은 명확하게 구분이 가능하다. versicolor와 virginica는 pca_component_1축을 기반으로 서로 겹치는 부분이 일부 존재하지만 비교적 잘 구분이 되었다. 이는 pca의 첫번째 새로운 축인 pca_component_1이 원본 데이터의 변동성을 잘 반영했기 때문이다. pca component별로 원본 데이터의 변동성을 얼마나 반영하고 있는지 알아보자.
print(pca.explained_variance_ratio_)
[0.72962445 0.22850762]
이번에는 기존 4차원 데이터를 2차원으로 pca 변환한 데이터 세트에 랜덤 포레스트를 적용해보자.
pca_X=irisdf_pca[['pca_component_1','pca_component_2']]
scores_pca=cross_val_score(rcf,pca_X,iris.target,scoring='accuracy',cv=3)
print("pca 변환 데이터 교차 검증 개별 정확도 : ",scores_pca)
print("PCA 변환 데이터 평균 정확도 :",np.mean(scores_pca))
PCA 변환 데이터 교차 검증 개별 정확도 : [0.88 0.88 0.88]
PCA 변환 데이터 평균 정확도 : 0.88
원본 데이터 세트 대비 예측 정확도는 PCA 변환 차원 개수에 따라 예측 성능이 떨어질 수 밖에 없다. 위 붓꽃 데이터의 경우 4개의 속성이 2개의 변환 속성으로 감소하면서 예측 성능의 정확도가 원본데이터 대비 10%하락했다. 10%의 정확도 하락은 비교적 큰 성능 수치의 감소이지만 3개의 속성이 2개로, 속성 개수가 50%감소한 것을 고려한다면 pca 변환후에도 원본 데이터의 특성을 상당부분 유지하고 있음을 알 수 있다.
5회차 회고록 (2022.08.09)
모각코도 어느덧 한 회차를 남겨두고 있는데, 이번 방학동안 알차게 AI 분야 공부를 한 것 같아 보람차다. 사이킷런을 들어만 봤었지 정확히 무엇인지 어떠한 함수들을 제공하고 있는지는 잘 몰랐었는데, 모각코 시간에 직접 코드를 따라치면서 어느정도 익힐 수 있었다. 마지막까지 열심히 해서 유종의 미를 거두고 싶다.