전 포스트에서 다중공산성을 확인하는 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
이렇게 몸무게와 키의 상관관계가 나오는 그래프가 있다.
이 그래프에서 정보의 유실을 최소화 하기 위해 가장 높은 분산을 가지는 선?을 찾는다.
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 |
댓글