본문 바로가기
ML/ML-Kaggle, 데이콘

다중공산성 해결 방법

by lucian 2021. 12. 29.

전 포스트에서 다중공산성을 확인하는 3가지 방법에 대해 설명했다.

scatterplot, heatmap, VIF 이렇게 총 3가지가 있다.

 

이번엔 다중공산성 해결 방법을 알아본다.

크게 3가지로 나뉘는데,

  • 변수 정규화
  • 변수 제거
  • PCA(주성분 분석)

 

먼저 

 

변수 정규화

변수 정규화는 이전 수치형 데이터 정규화 포스트에서 다루었다. https://lucian-blog.tistory.com/48?category=1002577 

보통 의사결정나무, 랜덤포레스트와 같이 트리기반 모델은 대소 비교를 통해 구분한다. 그렇기에 숫자와 단위에 크게 영향을 받지 않는다.

 

하지만 로지스틱 회귀, Lasso 등 평활함수모델(평활=smooth) 선형?함수같은 느낌인 것 같다.

여튼 이 모델들에는 숫자의 크기와 단위에 영향을 많이 받는다. (y=a*x1 + b*x2 + d*x3 +c)

x1의 숫자 크기는 거의 1~10사이인데, x2의 크기는 100이상이면 a,b 가중치의 차이가 크게 날 것이다.

그렇기에 변수 정규화는 중요하다.

 

접은 글은 데이터와 vif를 확인하는 코드이다.

더보기

 

# 데이터 다운로드 링크로 데이터를 코랩에 불러옵니다.

!wget 'https://bit.ly/3i4n1QB'

import zipfile
with zipfile.ZipFile('3i4n1QB', 'r') as existing_zip:
    existing_zip.extractall('data')
    
    
# 라이브러리 불러오기
import seaborn as sns
import pandas as pd

# VIF기능을 제공하는 라이브러리 불러오기
from statsmodels.stats.outliers_influence import variance_inflation_factor

# sklearn 의 MinMaxScaler 라이브러리 불러오기
from sklearn.preprocessing import MinMaxScaler

 

# 라이브러리 불러오기
import seaborn as sns
import pandas as pd

# VIF기능을 제공하는 라이브러리 불러오기
from statsmodels.stats.outliers_influence import variance_inflation_factor

# sklearn 의 MinMaxScaler 라이브러리 불러오기
from sklearn.preprocessing import MinMaxScaler

 

train = pd.read_csv('data/train.csv')

# 범주형 변수 제거(type)
train.drop(columns='type',inplace=True)

train

 

 

데이터의 VIF를 찾아본다. variance_inflaction_factor()함수로 train df의 값만 꺼내온 train_val array를 넣어주고, vif를 구할 변수들을 한개씩 넣어준다.(x1(index)==0,  x2(quality)==1)

# train 데이터의 VIF 계수 출력
train_val=train.values

vif_dataframe=pd.DataFrame()

vif_dataframe['columns']=train.columns
vif_dataframe['vif']=[variance_inflation_factor(train_val,i) for i in range(len(train_val[0]))]

vif_dataframe

변수 정규화 - code

자 이제 vif를 확인했으니, MinMaxSclaer로 데이터를 정규화 시킨 후 vif를 확인해보자.

# MinMaxScaler를 통해 변수 변환 

# MinMaxScaler를 "scaler"라는 변수에 지정해 봅시다.
scaler=MinMaxScaler()
# "scaler"를 train 으로 학습시켜주세요

train_scaler=scaler.fit_transform(train)
# "scaler"를 통해 train의 수치들을 변환 시키고 train_scale에 저장 해 주세요.

train_scaler

new_train=pd.DataFrame(train_scaler, columns=train.columns)
new_train

이렇게 MinMaxScaler로 변수들이 0~1사이의 값들로 바뀐 것을 볼 수 있다.

(이 MinMaxScaler는 이상치에 매우 민감하므로 반드시 이상치 전처리를 하고 실행해야한다.) 

 

 

 

 

이제 vif를 확인해보자.

# Sclaer 를 통해 변환된 데이터의 VIF 확인
scaled_vif_datafrme=pd.DataFrame()
scaled_vif_datafrme['columns']=train.columns
scaled_vif_datafrme['vif']=[variance_inflation_factor(train_scaler,i) for i in range(len(train_scaler[0]))]

scaled_vif_datafrme

 

아까보다 vif 계수가 많이 낮아진 것을 볼 수 있다. 하지만 아직 10이상의 값들이 많다.

10 이상의 값을 제거하거나, pca(주성분 분석으로) 차원을 축소해서 해결할 수 있다.

 


변수 제거 

변수 제거는 간단하다. vif가 10이상인 값을 제거해준 후 vif를 확인해보면 된다.

# 종속변수인 quality를 제외 한 vif 10이상 변수 제거
train_rm_vif10=train.drop(columns=['fixed acidity','total sulfur dioxide', 'density', 'pH', 'sulphates', 'alcohol'])
# VIF 10이상의 변수 제거 후 VIF 다시 확인
train_removed_vif=pd.DataFrame()
train_removed_vif['feature']=train_rm_vif10.columns

train_rm_val=train_rm_vif10.values
train_removed_vif['vif']=[variance_inflation_factor(train_rm_val,i) for i in range(len(train_rm_val[0]))]

train_removed_vif

 

 


PCA(주성분 분석)

주성분 분석이란?- 여러 변수간의 상관관계를 이용해서 대표하는 주성분을 추출한 후 차원을 축소하는 방법(feature extraction)이다. - https://lucian-blog.tistory.com/96

https://dacon.io/competitions/open/235698/talkboard/404069?page=1&dtype=recent

이렇게 몸무게와 키의 상관관계가 나오는 그래프가 있다.

이 그래프에서 정보의 유실을 최소화 하기 위해 가장 높은 분산을 가지는 선?을 찾는다.

 

https://dacon.io/competitions/open/235698/talkboard/404069?page=1&dtype=recent

1. 위에서 말한대로 선을 찾으면,

2. 선을 기준으로 데이터를 투영시킨다.(점들로부터 저 선에 직각이 되는 점들을 만들어준다.)

3. 이제 새로운 선을 기준으로 데이터를 표현해주면 된다.

 

이 안에는 공분산 행렬, 내적, 고유 벡터 등 다양한 수학적 기법이 들어간다....

https://angeloyeo.github.io/2019/07/27/PCA.html

- 이 공돌이님의 정리노트를 보는 것이 편하다....

 

 

이제 코드를 진행해보자. 데이콘에선 iris데이터를 가지고 4차원을 2차원으로 축소시켰다.

 

접은 글은 iris데이터를 가져온 코드이다.

더보기
from sklearn.datasets import load_iris
import pandas as pd 

# 사이킷런 내장 데이터 셋 API 호출

iris = load_iris()

# DataFrame으로 변환
df = pd.DataFrame(iris.data)
df.columns =  ['sepal_length','sepal_width','petal_length','petal_width']
df['target']=iris.target
df.head(3)
iris.target_names
df['target'].value_counts()

 

 

# 라이브러리 불러오기
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

# 정규화 라이브러리 호출
from sklearn.preprocessing import MinMaxScaler

# PCA 라이브러리 호출
from sklearn.decomposition import PCA

 

scatterplot으로 target을 대상으로 한 sepal width와 sepal length의 상관관계를 그려보자.

#setosa는 빨간색, versicolor는 노란색, virginica는 파란색
color=['r', 'y', 'b']

# setosa의 target 값은 0, versicolor는 1, virginica는 2. 
for i, c in enumerate(color):
  x_label=df[df['target']==i]['sepal_length']
  y_label=df[df['target']==i]['sepal_width']

  sns.scatterplot(x=x_label, y=y_label, color=c, label=iris.target_names[i])

# 각 target 별로 다른 색으로 scatter plot 
#plt.legend() #pyplot에선 범례(legend)을 표시하기 위해선 legend 함수를 써줘야 하나, seaborn 패키지에선 필요가 없는 듯 하다.
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.show()

 

이제 데이터를 정규화한 후 PCA를 진행해본다.

# Target 값을 제외한 모든 속성 값을 MinMaxScaler를 이용하여 변환
# 'sepal_length','sepal_width','petal_length','petal_width'
df_features=df.drop(columns='target')

scaler=MinMaxScaler()
scaled_df_features=scaler.fit_transform(df_features)

scaled_df=pd.DataFrame(scaled_df_features, columns=df_features.columns)
scaled_df

# PCA를 이용하여 4차원 변수를 2차원으로 변환
pca = PCA(n_components=2)

#fit( )과 transform( ) 을 호출하여 PCA 변환 / 데이터 반환
feature_pca=pca.fit_transform(scled_df_features)
feature_pca.shape

# PCA 변환된 데이터의 컬럼명을 각각 PCA_1, PCA_2로 지정
df_pca=pd.DataFrame(feature_pca, columns=['pca1','pca2'])
df_pca['target']=df['target']

df_pca

주성분 분석(PCA로 4차원이였던 featrue가 2차원으로 줄어들었다.)

 

#setosa는 빨간색, versicolor는 노란색, virginica는 파란색
color=['r', 'y', 'b']

# setosa의 target 값은 0, versicolor는 1, virginica는 2. 
# 각 target 별로 다른 색으로 scatter plot 

for i, c in enumerate(color):
  x_label=df_pca[df_pca['target']==i]['pca1']
  y_label=df_pca[df_pca['target']==i]['pca2']

  sns.scatterplot(x=x_label,y=y_label, color=c, label=iris.target_names[i])

from statsmodels.stats.outliers_influence import variance_inflation_factor

# VIF 10이상의 변수 제거 후 VIF 다시 확인
scaled_pca_df=pd.DataFrame()
scaled_pca_df['feature']=['pca1','pca2']
scaled_pca_df['vif']=[variance_inflation_factor(feature_pca,i) for i in range(len(feature_pca[0]))]

scaled_pca_df

 

'ML > ML-Kaggle, 데이콘' 카테고리의 다른 글

XGB(Extreme Gradient Boosting)  (0) 2021.12.30
차원 축소  (0) 2021.12.29
다중공산성  (0) 2021.12.17
Bayesian Optimization  (2) 2021.12.16
Hold-out, 교차검증(K-Flod), Stratified K-fold  (0) 2021.12.09

댓글