RL Researcher

피처 스케일링과 정규화(문제점 작성 X) 본문

Machine-Learning/Preprocessing

피처 스케일링과 정규화(문제점 작성 X)

Lass_os 2021. 1. 17. 02:52

1. 피처 스케일링


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

표준화(Standardization)는 데이터의 피처 각각 평균이 0이고 분산이 1인 Gaussian 정규분포를 가진 값으로 변환하는 것을 의미합니다. 표준화를 통해 변환될 피처 x의 새로운 i번째 데이터를 x(i)(new)라고 한다면 이 값은 원래 값에서 피처 x의 평균을 뺀 값을 피처 x의 표준편차로 나눈 값으로 계산할 수 있습니다.
$$x_{i}(new) = \frac{x_{i}-mean(x)}{stdev(x)}$$
일반적으로 정규화는 서로 다른 피처의 크기를 통일하기 위해 크기를 변환해주는 개념입니다. 예를 들어 피처 A는 거리를 나타내는 변수로서 값이 0 ~ 100KM로 주어지고 피처 B는 금액을 나타내는 속성으로 값이 0 ~ 100,000,000,000원으로 주어진다면 이 변수를 모두 동일한 크기 단위로 비교하기 위해 값을 모두 최소 0 ~ 최대 1의 값으로 변환하는 것입니다. 즉 개별 데이터의 크기를 모두 똑같은 단위로 변경하는 것입니다.
새로운 데이터 x_{i}(new)는 원래 값에서 피처 x의 최솟값을 뺀 피처 x의 최댓값과 최솟값의 차이로 나눈 값으로 변환할 수 있습니다.
$$x_{i}(new) = \frac{x_{i}-min(x)}{max(x)-min(x)}$$
그런데 사이킷 런의 전처리에서 제공하는 Normalizer 모듈과 일반적인 정규화는 큰 개념은 똑같지만 약간의 차이가 있습니다. 사이킷런의 Normalizer 모듈은 선형대수에서의 정규화 개념이 적용되었으며, 개별 벡터의 크기를 맞추기 위해 변환하는 것을 의미합니다. 즉 개별 벡터를 모든 피처 벡터의 크기로 나눠 줍니다. 세 개의 피처 x,y,z가 있다면 새로운 데이터 x_{i}(new)는 원래 값에서 세 개의 피처의 i번째 피처 값이 해당하는 크기를 합한 값으로 나눠 줍니다.
$$x_{i}(new) = \frac{x_{i}}{\sqrt{x_{i}^{2} +y_{i}^{2}+z_{i}^{2}}}$$

2. StandardScaler


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

코드로 확인해 보겠습니다.

import pandas as pd
from sklearn.datasets import load_iris

# 붓꽃 데이터 세트를 로딩하고 DataFrame으로 변환합니다
iris = load_iris()
data = iris.data

iris_df = pd.DataFrame(data=data,columns = iris.feature_names)

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

======================================================================

<output>
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

iris DataFrame의 평균과 분산을 확인 해보았을 때 가우시안 정규 분포를 가지고 있지 않습니다. StandardScaler를 사용해 표준화를 시켜 보겠습니다.

from sklearn.preprocessing import StandardScaler

# StandardScaler객체 생성
scaler = StandardScaler()
# StandardScaler로 데이터 세트 변환. fit()과 transform() 호출
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('feature 들의 평균 값')
print(iris_df_scaled.mean())
print('\nfeature 들의 분산 값')
print(iris_df_scaled.var())

======================================================================

<output>
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

모든 칼럼 값의 평균이 0에 아주 가까운 값으로, 분산은 1에 아주 가까운 값으로 변환되었음을 알 수 있습니다.

3. MinMaxScaler


MinMaxScaler는 데이터 값을 0과 1사이의 범위값으로 변환합니다.(음수 값이 있으면 -1에서 1값으로 변환합니다.) 데이터의 분포가 가우시안 분포가 아닌 경우에는 Min, Max Scale을 적용해 볼 수 있습니다. 코드로 확인해 보겠습니다.

import pandas as pd
from sklearn.datasets import load_iris

iris = load_iris()
data = iris.data

iris_df = pd.DataFrame(data = data,columns = iris.feature_names)

======================================================================

<output>
feature 들의 최솟값
sepal length (cm)   -1.870024
sepal width (cm)    -2.433947
petal length (cm)   -1.567576
petal width (cm)    -1.447076
dtype: float64

feature 들의 최댓값
sepal length (cm)    2.492019
sepal width (cm)     3.090775
petal length (cm)    1.785832
petal width (cm)     1.712096
dtype: float64

데이터의 최솟값과 최댓값의 분포가 가우시안 분포로 존재하지 않습니다. MinMaxScaler를 통해 정교화를 시켜 보겠습니다.

from sklearn.preprocessing import MinMaxScaler

# MinMaxScaler객체 생성
scaler = MinMaxScaler()
# MinMaxScaler로 데이터 세트 변환. fit()과 transform() 호출
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('feature 들의 최솟값')
print(iris_df_scaled.min())
print('\nfeature 들의 최댓값')
print(iris_df_scaled.max())

======================================================================

<output>
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

다음과 같이 MinMaxScaler를 통해 가우시안 분포를 만들어 줄 수 있습니다.

'Machine-Learning > Preprocessing' 카테고리의 다른 글

Data Encoding  (0) 2021.01.16
Comments