본문 바로가기

Data Handling/Data Preprocessing

피쳐 스케일링 (Feature Scaling)

* 해당 포스팅은 파이썬 머신러닝 완벽 가이드(권철민, 2019) 교재를 참고하여 공부하며 작성한 글입니다.

순서

  1. 표준화(Standardization) - StandardScaler
  2. 정규화(Normalization) - MinMaxScaler
  3. fit(), transform() 의 역할
  4. log 변환

 


 

 

1. 표준화 (Standardization) - StandardScaler

값들이 평균으로부터 얼마나 떨어져 있는지 나타내는 방법입니다.

평균을 빼고 표준편차로 나눠주면서 가우시안 정규분포(평균=0, 분산=1)를 가진 값들로 변환하는데, 

이는 단위가 서로 다른 특성들의 변화를 비교하기에 적합합니다.

 

예를 들어 키가 177이고 몸무게가 70인 열로 특성을 가지기 보다,

키와 몸무게가 평균보다 각각 얼만큼 큰지를 특성으로 가지는 것이 더 좋습니다.

 

아래 코드는 사이킷런 패키지 내장함수인 StandardScaler 를 통해 구현한 표준화 입니다.

from sklearn.preprocessing import StandardScaler

# 객체생성
scaler = StandardScaler()

# fit -> transform
scaler.fit(df) # df는 2차원 이상의 값이어야 함
df_scaled = scaler.transform(df)

# 배열형태로 반환되기 때문에 데이터 프레임으로 변환해주는 작업
df_scaled = pd.DataFrame(data = df_scaled)


# *** 만약 특정 열의 스케일링을 하고 싶은 경우 ***
A_n = scaler.fit_transform(df['A'].values.reshape(-1,1))
df.insert(0, 'A_scaled', A_n)
df.drop(['A'], axis=1, inplace=True)

* SVM, 선형회귀, 로지스틱 회귀의 경우에는 데이터가 가우시안 분포(연속확률분포)를 가지고 있다고 가정하고 구현되었기 때문에 표준화 하는게 바람직 함

 

 

2. 정규화 (Normalization) - MinMaxScaler

해당 특성의 최솟값과 최댓값을 활용하여 데이터값을 0과 1사이의 범위값으로 반환하는 방법입니다.

특성의 최솟값을 뺀 후, 최댓값과 최솟값이 차이값으로 나눈 값들로 반환되는데,

이는 단위가 서로 다른 특성들의 단위를 통일시켜주는 역할을 합니다.

 

예를 들어 특성 A는 0~100km의 단위를 가지고 특성 B는 0~100,000,000원의 단위를 가진다면,

알고리즘을 학습했을때 특성 B의 영향을 더 많이 받게 될 것입니다.

따라서 정규화를 통해 각 특성이 같은 범위를 가지도록 변환시켜줍니다.

 

정규화는 최솟값과 최댓값을 범위의 기준으로 사용하기 때문에 이상치에 굉장히 민감합니다.

아래 코드는 사이킷런 패키지 내장함수인 MinMaxScaler 를 통해 구현한 표준화 입니다.

from sklearn.preprocessing import MinMaxScaler

# 객체생성
scaler = MinMaxScaler()

# fit -> transform
scaler.fit(df) # df는 2차원 이상의 값이어야 함
df_scaled = scaler.transform(df)

# 배열형태로 반환되기 때문에 데이터 프레임으로 변환해주는 작업
df_scaled = pd.DataFrame(data = df_scaled)

 

 

3. fit(), transform()의 역할

fit()은 데이터 변환을 위한 기준 정보를 설정하는 역할을 합니다.

표준화의 경우에는 각 열의 평균과 표준편차 값들을, 정규화의 경우에는 최솟값과 최댓값을 계산하여 저장합니다.

 

transform()은 fit()으로 설정된 정보를 이용하여 데이터 변환을 하라는 명령입니다. 

표준화의 경우에는 평균을 빼고 표준편차로 나누고, 정규화의 경우에는 최솟값을 빼고 최댓값과 최솟값의 차이로 나누어 줍니다.

 

이 두 가지를 한번에 수행하는 fit_transform() 메서드도 있는데, 기 함수를 사용할 때에는 유의사항이 있습니다.

테스트 데이터를 scaler의 정보수집에 포함시키는 것인데요!!

테스트 데이터는 미지의 데이터이기 때문에 테스트를 하기 전까지는 어떤 상황에서도 사용되어서는 안됩니다.

 

따라서 훈련 데이터에서는 fit_transform()을 바로 사용할 수 있지만,

테스트 데이터에서는 훈련 데이터에서 설정된 정보를 가지고 transform을 해야하기 때문에 사용할 수 없습니다.

 

 

 

4. log 변환

특정 칼럼 혹은 타겟 변수(y)에 로그를 취해주면 모델의 성능이 올라가는 경우가 종종 있습니다.

어떤 원리로 성능이 올라가는 것일까요?

 

https://j1w2k3.tistory.com/392

 

위의 로그 그래프를 보면 그래프의 증가 폭이 갈수록 줄어들고 있습니다.

즉 x축 변화량에 따른 y축 변화량이 작다는 말인데요, 이는 큰 수를 같은 비율의 작은 수로 바꿔주는 역할을 합니다.

이러한 특징은 데이터 사이 값의 편차가 큰 특성의 경우에 유용하게 사용됩니다.

 

편차를 줄여주면 그래프의 왜도(skewness)와 첨도(kurtosis)를 줄일수 있기 때문에 정규성이 높아지는 장점도 있습니다.

정규화의 역할을 한다고 할 수 있겠네요!!

 

마지막으로 로그끼리의 곱은 덧셈으로, 나눗셈은 뺄셈으로 나타낼 수 있기 때문에 계산을 단순화 시켜주는 이점도 있습니다.

 

로그를 사용한 후에는 원래 값으로 되돌리는 작업이 필요한데요!!  아래와 같이 로그의 역함수인 지수함수를 이용하면 됩니다.

np.log() <-> np.exp()

np.log1p() <-> np.expm1()

 

* log1p = log + 1

* expm1 = exp - 1

# log1p 를 사용한 스케일링 사용 예시
A_n = np.log1p(df['A'])
df.insert(0, 'A_scaled', A_n)
df.drop(['A'], axis=1, inplace=True)