Machine Learning & DeepLearning

데이터 전처리(Data Preprosessing) - 데이터 인코딩(Encoding), 피처 스케일링과 정규화(Feature scaling and Normalization)

gellygelly 2022. 3. 25. 20:16

※ 본 글은 <파이썬 머신러닝 완벽 가이드(위키북스)> 책 내용을 공부하고 정리한 글입니다! 

 

피처 스케일링과 정규화

 

피처 스케일링(Feature Scaling): 서로 다른 변수의 값 범위를 일정한 수준으로 맞추는 작업. 대표적인 방법으로 표준화(Standardization)와 정규화(Normalization)가 있음. 

  • 표준화: 데이터의 피처 각각이 평균이 0이고 분산이 1인 가우시안 정규 분포를 가진 값으로 변환하는 것.

: 가우시안 정규 분포 / 출처:&nbsp;https://www.scienceall.com/%EA%B0%80%EC%9A%B0%EC%8A%A4-%EB%B6%84%ED%8F%ACgaussian-distribution-2/

표준화를 통해 변환될 피처 X의 새로운 i번째 데이터를 xi_new라고 한다면, 이 값은 원래 값에서 피처 x의 평균을 뺀 값을 피처 x의 표준편차로 나눈 값으로 계산할 수 있다. 

 

표준화를 통해 데이터를 변환하는 것은 RBF 커널을 이용하는 SVM(Support Vector Machine)이나 선형 회귀(Linear Regression), 로지스틱 회귀(Logistic Regression)과 같이 데이터가 가우시안 분포를 가지고 있다고 가정하고 구현된 알고리즘에서 매우 중요하다. 

 

  • 정규화: 서로 다른 피처의 크기를 통일하기 위해 크기를 변환하는 것. 즉, 개별 데이터의 크기를 모두 똑같은 단위로 변경하는 것. 

새로운 데이터 xi_new는 원래 값에서 피처 x의 최솟값을 뺀 값을 피처 x의 최대값과 최솟값의 차이로 나눈 값으로 변환할 수 있다. 

 

참고로, 사이킷런에서 제공하는 Normalizer 모듈은 선형대수에서의 정규화 개념이 적용됐다. 이는 개별 벡터의 크기를 맞추기 위해 변환하는 것을 의미하며 수식은 아래와 같다. 

 

 

StandardScaler

standardScaler는 표준화를 쉽게 지원하기 위한 클래스로, 개별 피처를 평균이 0이고 분산이 1인 값으로 변환해준다. 

 

from sklearn.datasets import load_iris
import pandas as pd
from sklearn.preprocessing import StandardScaler

# dataframe으로 변환
iris = load_iris()
iris_data = iris.data
iris_df = pd.DataFrame(data=iris_data, columns=iris.feature_names)

print('feature들의 평균 값')
print(iris_df.mean())
print('\nfeature들의 분산 값')
print(iris_df.var())

# StandardScaler 객체 생성
scaler = StandardScaler()

scaler.fit(iris_df) # 데이터 변환을 위한 기준 정보 설정
iris_scaled = scaler.transform(iris_df) # 데이터 변환

# transform() 시 스케일 변환된 데이터 세트가 NumPy ndarray로 반환돼 이를 Dataframe으로 변환
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
print("\n -- standardScaler 적용 후 -- \n")
print('feature들의 평균 값')
print(iris_df_scaled.mean())
print('\nfeature들의 분산 값')
print(iris_df_scaled.var())

 

## 출력 ##
feature들의 평균 값
sepal length (cm)    5.843333
sepal width (cm)     3.057333
petal length (cm)    3.758000
petal width (cm)     1.199333
dtype: float64

feature들의 분산 값
sepal length (cm)    0.685694
sepal width (cm)     0.189979
petal length (cm)    3.116278
petal width (cm)     0.581006
dtype: float64

 -- standardScaler 적용 후 -- 

feature들의 평균 값
sepal length (cm)   -1.690315e-15
sepal width (cm)    -1.842970e-15
petal length (cm)   -1.698641e-15
petal width (cm)    -1.409243e-15
dtype: float64

feature들의 분산 값
sepal length (cm)    1.006711
sepal width (cm)     1.006711
petal length (cm)    1.006711
petal width (cm)     1.006711
dtype: float64

 

MinMaxScaler

 

MinMaxScaler는 데이터값을 0과 1 사이의 범위 값으로 변환(음수 값이 있으면 -1 ~ 1값으로 변환)하며 데이터의 분포가 가우시안 분포가 아닐 경우에 적용해볼 수 있다. 

 

from sklearn.datasets import load_iris
import pandas as pd
from sklearn.preprocessing import MinMaxScaler

# dataframe으로 변환
iris = load_iris()
iris_data = iris.data
iris_df = pd.DataFrame(data=iris_data, columns=iris.feature_names)

print('feature들의 최솟값')
print(iris_df.min())
print('\nfeature들의 최댓값')
print(iris_df.max())

# MinMaxScaler 객체 생성
scaler = MinMaxScaler()

scaler.fit(iris_df) # 데이터 변환을 위한 기준 정보 설정
iris_scaled = scaler.transform(iris_df) # 데이터 변환

# transform() 시 스케일 변환된 데이터 세트가 NumPy ndarray로 반환돼 이를 Dataframe으로 변환
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
print("\n -- MinMaxScaler 적용 후 -- \n")
print('feature들의 최솟값')
print(iris_df_scaled.min())
print('\nfeature들의 최댓값')
print(iris_df_scaled.max())

 

## 출력 ##

feature들의 최솟값
sepal length (cm)    4.3
sepal width (cm)     2.0
petal length (cm)    1.0
petal width (cm)     0.1
dtype: float64

feature들의 최댓값
sepal length (cm)    7.9
sepal width (cm)     4.4
petal length (cm)    6.9
petal width (cm)     2.5
dtype: float64

 -- MinMaxScaler 적용 후 -- 

feature들의 최솟값
sepal length (cm)    0.0
sepal width (cm)     0.0
petal length (cm)    0.0
petal width (cm)     0.0
dtype: float64

feature들의 최댓값
sepal length (cm)    1.0
sepal width (cm)     1.0
petal length (cm)    1.0
petal width (cm)     1.0
dtype: float64

학습 데이터와 테스트 데이터의 스케일링 변환 시 유의점

StandardScaler나 MinMaxScaler와 같은 Scaler 객체를 이용해 데이터의 스케일링 변환 시, 아래와 같은 메소드를 사용한다. 

  • fit(): 데이터 변환을 위한 기준 정보 설정(데이터 세트의 최솟값/최댓값 설정) 
  • transform(): 설정된 데이터를 이용해 데이터 변환
  • fit_transform(): fit()+transform()

학습 데이터와 테스트 데이터에 위와 같은 함수를 적용할 시 유의할 점은 학습 데이터 세트로 fit()과 transform()을 수행하면 테스트 데이터 세트에서는 fit()을 수행하지 않고, 학습 데이터 세트에서 적용한 스케일링 기준 정보를 그대로 transform() 변환을 수행해야 한다. 

 

요약하면,

  • 학습 데이터 세트: fit() + transform() 수행
  • 테스트 데이터 세트: 학습 데이터에서 fit()을 수행한 정보를 그대로 이용하여 transform() 수행
  • !! 테스트 데이터에 따로 fit() 하지 않기 !! -> 학습 데이터와 테스트 데이터의 스케일링 기준 정보가 달라져 올바른 정보 도출 불가능 
  • 데이터 세트를 학습 데이터와 테스트 데이터로 분리하기 전, 미리 스케일링 변환을 수행하면 편하다!