본문 바로가기

Codestates AI 부트캠프/1. Introduction to Data Sceince

[기초 수학] 3-2 PCA

1. 공분산과 상관계수

공분산
- 변수 간의 연관성을 보여주는 지표
- 두 변수에 대하여 한 변수가 변화할 때, 다른 변수가 어떠한 연관성을 갖고 변하는 지를 나타낸 값
- 공분산이 음수라면 두 변수가 반대 방향으로 움직이는 경향성, 양수라면 같은 방향으로 움직이는 경향성을 가진다고 볼 수 있다
- 공분산의 절댓값이 클수록 두 변수의 연관성도 크다고 볼 수 있다
- 다만 연관성이 같더라도 변수 자체의 값(스케일)이 크면 공분산이 크게 나온다

 

#공분산 구하기
df.cov() #dataframe 형태로 출력
np.cov(df.T) #array 형태로 출력


상관계수
- 공분산을 두 변수의 표준편차로 나눈 값
- 위에서 변수의 스케일에 따라 공분산이 달라진다고 했는데, 그 부작용을 제거할 수 있는 지표
- 1에서 1 사이의 값을 사진다. 상관계수가 1이라면 한 변수가 다른 변수에 대해 완벽한 양의 선형관계를 가진다는 것을 의미

- 이때, 상관계수가 0이라고 해서 아예 두 변수간의 연관성이 없는 것은 아니다. 아래 이미지와 같이 어떠한 패턴을 가질수도 있다

 

#상관계수 구하기
df.corr()
np.corrcoef(df.T)


2. 선형대수

함수 변환
- 임의의 벡터는 함수f(또는 행렬T)에 의해 변환된다

eigenvector
- 행렬 T에 의해 변환이 시도되지만, 크기만 변하고 방향은 바뀌지 않는 벡터

eigenvalue
- eigenvector가 변화한 크기

eigenstuff
- eigenvector와 eigenvalue를 함께 이르는 말
- 행렬T의 column수만큼 존재한다

 

#eigenstuff 구하기
values, vectors = np.linalg.eig(df)
print("\n Eigenvalues: \n", values)
print("\n Eigenvectors: \n", vectors)


3. PCA (주성분 분석, Principal Component Analysis)

column 수가 많을 때(=고차원 데이터), 연관성이 짙은 column들끼리 합쳐주는 과정. column 수가 많다고 머신러닝에 유리한 것은 아니다. 차원 축소 기술 중 하나.

연관성이 큰 컬럼들끼리 묶어 pca를 진행하는 것이 좋다. 예를 들어, 한 데이터셋에 a,b,c,d,e,f 여섯개의 컬럼이 있는데 (b,c,d)끼리, (e,f)끼리 연관성이 크다면 각각 진행해주도록 한다.

아래 그림과 같이 데이터가 두개 이상의 컬럼과 성분이 존재할 때, 이 데이터들을 가장 효과적으로 사영할 수 있는 선을 찾는다. 사영이란 데이터에서 선으로 수선의 발을 내리는 것을 의미하는데, 그 수선의 거리들의 합이 가장 짧은 선이 PC1이 된다. PC2와 PC3 등 이후의 PC들은 PC1에 직교하는 선으로 자동 결정된다. 

 

과정

① 데이터셋 표준화

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
df_scaled = scaler.fit_transform(df)


② PCA할 컬럼 선별

 

#컬럼별 상관계수 구하기
df_corr = df.corr()
df_corr

#상관계수 시각화
sns.set(rc = {'figure.figsize':(15,8)})
sns.heatmap(df_corr, annot=True)
plt.title('Annoteat cell with numeric value', fontsize=20)
plt.show()

 

위 이미지에서 1에 가까운 상관계수를 가진 컬럼들을 식별할 수 있다. 여기엔 없지만 음의 상관관계가 높은 컬럼들도 있으니 양수, 음수 모두 따져보아야 한다.

③ PCA 시행
이때, eigenstuff가 사용된다. eigenvalue 값이 가장 큰 eigenvector가 PC1이 되기 때문이다.

 

from sklearn.decomposition import PCA

pca = PCA() 
pca.fit(df_scaled)
df_pca = pca.transform(Z)


④ PC 갯수 결정
위의 결과를 토대로 PC별 분산을 표시한 그림을 그려본다. PC1부터 분산을 누적으로 나타내 총 PC의 분산 합이 70-80% 정도가 되면 무난하다. 아래 이미지로 보면 2-3개 정도가 적당해보인다

⑤ PC 컬럼 추출

#2개의 PC를 구하기로 결정
pca = PCA(2) 
pca.fit(df_scaled)

df_pca = pca.transform(pca_scaled)

pca_columns = pd.DataFrame(df_pca, columns=['pc1', 'pc2'])
pca_columns