본문 바로가기

Lecture ML

머신러닝 강좌 #5] 피처스케일링 (표준화 / 정규화) / StandardScler, MinMaxScaler

반응형

서로 다른 변수의 값 범위를 일정한 수준으로 맞추는 작업을 피처 스케일링이라고 합니다. 대표적인 방법으로 표준화(Standardiaztion)와 정규화(Normaliaztion)가 있습니다.

 

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

 

사이킷런에서 제공하는 대표적인 피처 스케일 클래스인 StandardScaler와 MinMaxScaler를 알아보겠습니다.

 


1. StandardScler

 

StandardScaler : 피처스케일링 정규화

서로 다른 변수의 값 범위를 일정한 수준으로 맞추는 작업을 피처 스케일링(Feature Scaling)이라고 합니다. 대표적인 방법으로 표준화(Standardization)와 정규화(Normaliaztion)가 있습니다. 사이킷런에서

nicola-ml.tistory.com

 

 


2. MinMaxScaler

 

MinMaxScler는 데이터 값을 0과 1 사이의 범위 값으로 변환합니다. 음수 값이 있으면 -1에서 1 값으로 변환합니다. 데이터의 분포가 가우시안 분포가 아닐 경우에는 Min, Max Scaler을 적용해 볼 수 있습니다. 

 

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

iris_set = load_iris()
iris_data = iris_set.data
irisDF = pd.DataFrame(data=iris_data, columns=iris_set.feature_names)

scaler = MinMaxScaler()
scaler.fit(irisDF)
iris_scaled = scaler.transform(irisDF)

#transform()시 스케일 변환된 데이터 세트가 Numpy ndarry로 반환돼 이를 DataFrame으로 변환
irisDF_scaled = pd.DataFrame(data=iris_scaled, columns=iris_set.feature_names)
print(irisDF_scaled.min())
print(irisDF_scaled.max())

 

하기 값을 보면 모든 피처에 0에서 1사이의 값으로 변화하는 스케일링이 적용됐음을 알 수 있습니다.

sepal length (cm)    0.0
sepal width (cm)     0.0
petal length (cm)    0.0
petal width (cm)     0.0
dtype: float64
sepal length (cm)    1.0
sepal width (cm)     1.0
petal length (cm)    1.0
petal width (cm)     1.0
dtype: float64

 


3. 주의점

 

주의할 내용으로 학습 데이터 세트와 테스트 세트에 fit()과 transform()을 적용할 때 주의가 필요합니다. Scaler객체를 이용해 학습 데이터 세트로 fit()과 transform()을 적용하면 테스트 데이터 세트로 다시 fit()을 수행하지 않고 학습 데이터 세트로 fit()을 수행한 결과를 이용해 transform() 변환을 적용해야 한다는 것입니다. 

 

즉, 학습 데이터로 fit()이 적용된 스케일링 기준 정보를 그대로 테스트 데이터에 적용해야 하며, 그렇지 않고 테스트 데이터로 다시 새로운 스케일링 기준 정보를 만들게 되면 학습 데이터와 테스트 데이터의 스케일링 기준 정보가 서로 달라지기 때문에 올바른 예측 결과를 도출하지 못할 수 있습니다. 

 

머신러닝 모델은 학습 데이터를 기반으로 학습되기 때문에 반드시 테스트 데이터는 학습 데이터의 스케일링 기준에 따라야 합니다. 따라서 테스트 데이터에 다시 fit()을 적용해서는 안 되며 학습 데이터로 이미 fit()이 적용된 Scaler객체를 이용해 transform()으로 변환해야 합니다. 

 

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

iris_set = load_iris()
iris_data = iris_set.data
irisDF = pd.DataFrame(data=iris_data, columns=iris_set.feature_names)

train_array = np.arange(0,11).reshape(-1,1)
test_array = np.arange(0,6).reshape((-1,1))

scaler = MinMaxScaler()
scaler.fit(train_array)
train_caled = scaler.transform(train_array)
print("원본 train_array :", np.round(train_array.reshape(-1),2))
print("Scale된 train_array :", np.round(train_caled.reshape(-1),2))

scaler.fit(test_array)
test_scaled = scaler.transform(test_array)
print("원본 test_array :", np.round(test_array.reshape(-1),2))
print("Scale된 train_array :", np.round(test_scaled.reshape(-1),2))

*reshpae의 형태변환에 대해 참고하고 싶다면 [이곳]

아래 값을 보면 원본 train과 test의 Scaled값이 다름을 알 수 있습니다. 이러면 안됩니다.

원본 train_array : [ 0  1  2  3  4  5  6  7  8  9 10]
Scale된 train_array : [0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]
원본 test_array : [0 1 2 3 4 5]
Scale된 train_array : [0.  0.2 0.4 0.6 0.8 1. ]

 

transform에 test데이터를 넣으면 아래와 같이 값이 달라진다.

# scaler.fit(test_array)
test_scaled = scaler.transform(test_array)
print("원본 test_array :", np.round(test_array.reshape(-1),2))
print("Scale된 train_array :", np.round(test_scaled.reshape(-1),2))
원본 train_array : [ 0  1  2  3  4  5  6  7  8  9 10]
Scale된 train_array : [0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]
원본 test_array : [0 1 2 3 4 5]
Scale된 train_array : [0.  0.1 0.2 0.3 0.4 0.5]

 

학습 데이터와 테스트 데이터의 fit(), transform(), fit_transform()을 이용해 스케일링 변환 시 유의할 점을 요약하면 다음과 같습니다.

 

1. 가능하다면 전체 데이터의 스케일링 변환을 적용한 뒤 학습과 테스트 데이터로 분리

2. 1이 여의치 않다면 테스트 데이터 변환 시에는 fit()이나 fit_transform()을 적용하지 않고 학습 데이터로 이미 fit()된 Scaler객체를 이용해 transform()으로 변환

 

 

반응형