[머신러닝] 모델 신뢰도 향상을 위한 피처 스케일링 (Feature Scaling)
공부/코딩

[머신러닝] 모델 신뢰도 향상을 위한 피처 스케일링 (Feature Scaling)

 이번 글도 머신러닝 모델의 신뢰도를 올리기 위한 방법에 대해 소개합니다. 다들 아시겠지만 산점도도 그렇고 아래의 글에서 시작됐습니다. 흐름을 보고 싶다면 한번 읽어보세요.

 

[머신러닝] KNN으로 데이터 분류하기 (with Scikit-Learn)

[Pandas] 6. 폴더 내 여러 데이터 프레임(파일) 합치기 [Pandas] 5. 조건에 맞춰 데이터 추출하고 수정하기 (Kaggle 에서 가져온 Gear Defection 데이터 이용) Kaggle 이라는 사이트가 있습니다. 데이터 사이언

senti-mech.tistory.com

 

1. 피처 스케일링(Feature Scailing)이란?


 오늘 소개할 것은 피처 스케일링 (Feature Scaling)입니다. 데이터의 독립변수(independent variables)나 특징(Feature)의 범위를 정규화 하는 것입니다. 보통 데이터 전처리 과정에 포함됩니다.

 

 예를 들어 봅시다. 저는 밀도와 탄성계수(Young's Modulus)로 가격을 예측하는 모델을 만들고 싶습니다. 밀도는 2500kg ~7750kg/m^3 이고, 탄성계수는 200~230GPa 정도 됩니다. 이 것으로 식을 만들면, 두 변수 간에 단위도 다르고 범위에도 차이가 있습니다. 아마 밀도 앞에 붙는 계수는 탄성계수보다도 더 크겠죠. 이러면 작은 값의 특성에는 민감하게 반응하고, 큰 값의 특성은 무시될 수 있습니다.

 

 따라서, 피처 스케일링을 통해 모든 특성이 동일한 범위 내에 있도록 만드는 것입니다.

 

 특성이 어떤 것을 의미하는 지 궁금하신 분들은 아래 글을 추천 드립니다.

 

What is Feature

A Jekyll theme for documentation

kh-kim.github.io

 

2. 피처 스케일링 방법 - 표준화 (Standardzation)


출처: 위키피디아

 

 표준화(Standardzation)은 데이터의 평균을 0으로, 표준편차를 1로 만들어 데이터를 정규분포에 가깝게 만드는 과정입니다. 

 

여기서 m 은 평균, σ는 표준편차입니다. 이게 전부구요, 직접 해볼 일만 남았습니다.

 

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()

x = data["sensor1"]
y = data["sensor2"]

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 2088)

scaler.fit_transform([x_train]) // 해당 함수는 array로 입력값을 받음

결과값

 잘못된 코드입니다.

 

 우선 해야할 것은 학습 데이터와 평가 데이터를 분리하는 것입니다. 우리는 사용하지 않은 데이터로 모델을 시험할 것이기 때문입니다. 두 데이터를 포함한 채로 정규화 해버리면, 시험 데이터인데도 이미 모델에 반영이 되어버리는 상황이 옵니다.

 

 처음엔 위 코드처럼 했습니다. x는 시리즈가 됩니다. 그런데, fit_transform()은 입력을 array로 받습니다. 그래서 대괄호를 씌웠습니다. 그러니 하나의 리스트에 모든 값이 들어간 상황이 벌어졌습니다. 각각의 데이터가 하나의 독립변수가 된 것입니다. 그래서 아래 코드를 시도합니다.

 

import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

data = pd.read_csv("total.csv")
displacement = data[['sensor1','sensor2']]

dis_train, dis_test, = train_test_split(displacement, test_size = 0.3, random_state = 2088)

scaler = StandardScaler() # 표준화 모듈 만들기

dis_train_std = scaler.fit_transform(dis_train) # dis_train으로 모델 만들고 반환
dis_test_std = scaler.transform(dis_test) # 모델 만드는거 없이 dis_test를 넣기만 함

dis_test_std

결과값

 x,y 데이터를 displacement 하나로 합친 뒤 실행하였습니다. 이러면 매 행의 좌표값이 각각의 리스트로 어레이에 들어가게 됩니다. 그래서 실행이 되는 것입니다.

 

 위 코드에선 fit_transform을 사용 했지만, fit()과 transform()을 따로 사용해도 됩니다. 예를 들어, scaler.fit(dis_train)으로 학습 시키고, dis_test_std = scaler.tranform(dis_test) 처럼요. 이미 scaler 모듈은 fit()을 통해 dis_train 으로 만들어졌기 때문입니다.

 

 이제 표준화가 제대로 되었는지 확인 할 차례입니다.

 

df_dis = pd.DataFrame(dis_test_std)
df_dis.describe()

 평균과 표준편차 각각 0과 1에 근접한 것을 확인할 수 있습니다.

 

3. 피처 스케일링 방법 - 최소 최대 정규화(Min-Max Normalization)


 최소-최대 정규화(Min-Max Normalization)는 표준화보다 직관적입니다. 데이터의 최소값을 0으로, 최대값을 1로 만들어 모든 데이터를 0과 1사이의 숫자로 나타내는 방법입니다. 수식은 아래와 같습니다.

 

dis_minmax = (dis_train - dis_train.min())/(dis_train.max() - dis_train.min())
dis_minmax

결과값

 생략된 많은 값들도 0.5 주변에 모여있습니다. 왜 그럴까요? 바로 최소-최대 정규화의 단점 때문입니다. 이상치(Outlier)에 취약하다는 점입니다. 예를 들어, 100개의 데이터 모두 값이 10인데, 딱 두 개만 각각 1과 100이라면 모델이 이상해지는겁니다. 아마 이전 글에서 본 아웃라이더들 때문이 이런 일이 벌이진게 아닌가 생각합니다.

 

 sklearn 으로는 어떻게 사용할까요?

 

from sklearn.preprocessing import MinMaxScaler

mm_scaler = MinMaxScaler(feature_range=(0,5)) # 데이터 값을 0~5범위로 변환
mm_scaler.fit(dis_train) # 데이터로 모델 생성
dis_test_mm = mm_scaler.transform(dis_test)

dis_test_mm

결과값

 이번에는 sklearn 라이브러리의 MinMaxScaler을 이용했습니다. 전체적인 사용 방법은 표준화 모듈과 비슷합니다. fit과 transform을 사용하니까요. 데이터를 보니 시험용 데이터에는 학습용 데이터보다 더 큰 이상치가 있나봅니다. 단 하나의 점도 0 주변에 가지 못한 걸 보니, 학습용 데이터의 최소값이 이상치인 것도 확실해보입니다.

 

 다음 시간엔 이상치를 제거하는 방법을 찾아보겠습니다. 당연한 수순입니다.