Machine Learning

머신러닝 프로젝트 전처리 예시 1

with_AI 2022. 5. 30. 15:51

Can you cut the time a Mercedes-Benz spends on the test bench?

https://www.kaggle.com/c/mercedes-benz-greener-manufacturing

 

Mercedes-Benz Greener Manufacturing | Kaggle

 

www.kaggle.com

이 프로젝트에서는...

feature 엔지니어링을 잘해야한다.

적절한 feature들로만 성능이 높게 나올 수 있다.

주어진 공정들의 시간을 더해서 테스트 시간을 예측한다.

보안상 때문에 x1, x2, 등으로 이름이 붙여있음

카테고리, 0과1 등 label을 추정을 해야만 하는 한계도 있음

 

프로젝트 목적

test_bench time predict

 

ML 프로젝트 수행 순서

- 라이브러리, 데이터 불러오기

- EDA 수행

- 전처리 수행, feature engineering

- 데이터 분할

- 학습 진행

- 하이퍼 파라미터 튜닝 수행 (과적합 주의)

- 최종 테스트 진행

 

상관관계 분석, VIP : 다중 공산성 제거

from statsmodels.stats.outliers_influence import variance_inflation_factor

 

하이퍼파라미터 튜닝을 위한 라이브러리 optuna

import optuna

 

 

김용담 강사님의 코드 분석

 

1. 사용할 라이브러리와 데이터를 불러온다.

# 데이터분석 4종 세트
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 데이터를 불러옵니다.
train = pd.read_csv("../input/mercedes-benz-greener-manufacturing/train.csv.zip")
test = pd.read_csv("../input/mercedes-benz-greener-manufacturing/test.csv.zip")

 

2. EDA

1. 결측치는 없다

  1. dtype이 object인 column : X0 ~ X8까지 8개. (categorical feature)

-> 어떻게 처리할지 고민해야함. (Ordinal Encoding VS One-Hot Encoding)
- (이런것을 고민하는구나, 과연 어떤 선택을 어떠한 근거로 하셨을까)

-> categorical feature들은 종류 정보들이 알파벳으로 되어있으며(anomynized) 이 정보들 대비 target값의 차이가 있는지 확인. (특별하게 관련 없음)
- (feature 하나하나 잘 살펴보고 target과 관련이 있는지 확인하기)

-> binary feature들중에서 0만 가지고 있는 column들이 있음. (0만?..그러면 왜있는거지)

-> 정보가 충분하지 않다고 판단(target value와의 관련성 0) 삭제. 

  1. target distribution -> train data에 180을 넘는 데이터가 하나 있음. 이 데이터를 outlier라고 생각하고 제거. 

- (이상치는 찾아서 제거한다.)

 

### outlier 찾아서 지우기!

plt.figure(figsize=(12, 8))
#sns.histplot(data=train, x="y")
#sns.boxplot(data=train, x="y", whis=3)
sns.boxplot(data=train, x="y")
## train에 y column이 161을 넘는 데이터를 제거하자
outliers = train.loc[train.y > 135] ## IQR*1.5
train = train.drop(index=outliers.index)
train

 

y에 대한 boxplot

카테고리, 바이너리 column을 나눈다.

# X0 ~ X8 : categorical variables --> 8개
cat_vars = train.columns[2:10]
cat_vars
# X10 ~ : binary variables
binary_vars = train.columns[10:]
binary_vars

 

바이너리에서 0 과 1의 비율을 확인 (X는 384개나 있음..)

# binary variable들의 0과 1의 구성 비율을 확인합니다!

# 1. value_counts 함수를 이용한 방법
# temp = train.X10.value_counts(normalize=True).values * 100
# print(f"0의 비율: {temp[0]:.4f}%, 1의 비율: {temp[1]:.4f}%")

# 2. 1의 개수를 이용한 방법
all0_cols = [] # column에 있는 모든 데이터가 다 0인 케이스.

for col in binary_vars:
    one_percent = train[col].mean() * 100 # 1의 비율을 퍼센트로 표현
    if one_percent == 0.0: # 1의 개수가 0인 경우.
        all0_cols.append(col) ## 모든 값이 0인 column들을 추가합니다.
        
    print(f"[{col}]  0의 비율: {100 - one_percent:.2f}%\t1의 비율: {one_percent:.2f}%")
[X10]  0의 비율: 98.65%	1의 비율: 1.35%
[X11]  0의 비율: 100.00%	1의 비율: 0.00%
...
...
...

이런식으로 출력이 된다.

 

여기서 1이 없는 경우의 col은 삭제

train = train.drop(columns=all0_cols)
train

4154 rows × 365 columns 으로 columns수가 줄어들었다.

 

 

3. feature engineering

1. correlation

1. VIF

1. PCA

 

상관계수가 0.7보다 높은 것들을 추리기

# 1. Correlation이 높은 변수들 찾기 --> 필요없는 column : ID, y
temp = train.drop(columns=["ID", "y"])
corr = temp.corr() # 363 x 363
threshold = 0.7

#display(corr.loc[corr.X1 > threshold])

# e.g. X1 ----> [X3, X6, X10]
#      X2 ----> [....]       
#      X3 ----> [X1, X6, X10, ..., ...] (skip)
#      X4 ----> [....]
high_correlated_cols = []

for col in temp.columns:
    if col in high_correlated_cols:
        continue
    temp_cols = list(corr.loc[(corr[col] > threshold) | (corr[col] < -threshold)].index[1:]) # 보고 있는 column을 제외하고 threshold보다 상관계수가 높은 column들을 리스트로 변환.
    high_correlated_cols = high_correlated_cols + temp_cols # 리스트 누적
    
high_correlated_cols = set(high_correlated_cols) # 중복 column들 제거
high_correlated_cols

위와같이 0.7이상의 상관관계를 가진 col이 매우 많았다.

 

 

VIF가 10이 넘는 변수 찾기

VIF_i = 1/ 1 - R2_i

다중공산성 방지를 위해

 

# 2. VIF가 10이 넘는 변수들 찾기
## VIF_i = 1 / 1 - R2_i

from statsmodels.stats.outliers_influence import variance_inflation_factor

vif_list = [variance_inflation_factor(temp, idx) for idx in range(len(temp.columns))]

vif_df = pd.DataFrame(index=temp.columns, data=vif_list, columns=["VIF"])
vif_df.sort_values(by="VIF", ascending=False) # VIF가 큰 순서대로 정렬해서 만든 DataFrame

## VIF가 가장 큰 (또는 10보다 큰 column중에 하나)를 골라서 제거 한 뒤에 다시 VIF 계산. (loop)
## Continue..

이런식의 VIF 결과가 나온다.

 

3. PCA

차원의 저주를 피하기 위해 PCA 진행

# 3. PCA(Principal Component Analysis)를 이용하여 변수 크기 줄이기
from sklearn.decomposition import PCA

## PCA의 n_components -----> hyper-parameter!
# 1. n_components = 6 : 6차원으로 내려주세요.
# 2. n_components = 0.90 : 원본 데이터의 분포를 90% 보존하는 차원으로 내려주세요.

#pca = PCA(n_components=15)
pca = PCA(n_components=0.95)
X = pca.fit_transform(temp) # 주성분을 기준으로 데이터를 "저차원"으로 변환
pca_columns = [f"PC{i}" for i in range(X.shape[1])]
pca_df = pd.DataFrame(columns=pca_columns, data=X)
pca_df

 

PCA를 진행하기 전에는 363개의 COL수였는데, PCA를 진행하고 나니 12개의 특성으로 줄일 수 있었다.

이때 이 PCA는 원본 데이터의 95%를 보존하면서 저차원으로 내린 것을 알 수 있다.

'Machine Learning' 카테고리의 다른 글

나이브베이즈 (Naive_bayes) 분류 모델  (0) 2022.05.27
LightGBM에 대하여  (0) 2022.05.25
XGBoost 기초 설명  (0) 2022.05.25
Lasso 와 Ridge 회귀 (regression)  (0) 2022.05.25
선형회귀와 LGBM 실습  (0) 2022.05.17