Snoopy [ML] 17. 데이터 전처리 (6) - 스케일링(z-score, min-max, robust)
머신러닝과 딥러닝/ML 개념정리

[ML] 17. 데이터 전처리 (6) - 스케일링(z-score, min-max, robust)

Sooyoon Jeong 2022. 11. 14.

멋쟁이 사자처럼 AI스쿨 7기 오늘코드 박조은 강사님의 수업자료를 바탕으로 포스팅하였습니다.


1. 변수스케일링이란?

feature의 범위를 조정하여 정규화하는 것(수치형 피쳐)

 

트리기반 모델은 데이터의 절대적인 크기보다는 상대적인 크기에 영향을 받기 때문에 따로 스케일링을 해줄 필요는 없지만, 다른 모델을 사용할 때는 변수 스케일링을 해주어야 올바른 분석을 할 수 있다.(특히 회귀에서는 유용하다.)

 

2. 스케일링이 왜 중요할까?

1️⃣ feature의 범위가 다르면 비교가 어렵다.

2️⃣ 일부 머신러닝 모델(회귀 등에서 다항식 연산을 할 때 등)에서는 제대로 작동하지 않는다.

3️⃣ 스케일링이 잘 되어 있으면 서로 다른 변수끼리 비교하는 것이 편리하고, 성능이 상승한다.

4️⃣ feature scaling 없이 작동하는 알고리즘(경사하강법, KNN, clustering 같은 거리 기반 알고리즘 등)에서 더 빠르게 작동한다. (단, 트리 기반 알고리즘은 Feature Scaling의 영향을 잘 받지 않는다.)

5️⃣ 일부 Feature Scaling은 이상치에 강하다는 장점이 있다.

(뒤에서 학습하겠지만, Robust scaling의 경우 사분위수를 기준으로 값을 스케일링하기 때문에, 이상치가 매우 큰 값이나 매우 작은 값을 갖는 경우에 이런 부분을 완화시켜주는 효과가 있습니다.)

 

3. 스케일링 방법

1️⃣ Normalization - Standardization (Z-score scaling)
정의: 평균을 제거하고 데이터를 단위 분산으로 스케일링
공식: z = (X - X.mean) / std
장점: 표준 편차가 1이고 평균을 0으로 하는 표준 정규 분포를 갖도록 조정
단점: 변수가 치우쳐 있거나 특이치가 있는 경우 좁은 범위의 관측치를 압축하여 예측력을 손상시킴

2️⃣ Min-Max scaling
정의: 각 feature의 크기를 지정된 범위로 확장하여 변환 (기본값은 [0,1])
공식: X_scaled = (X - X.min) / (X.max - X.min)
단점:변수가 치우쳐 있거나 특이치가 있는 경우 좁은 범위의 관측치를 압축하여 예측력을 손상시킴

3️⃣ Robust scaling
정의: 중앙값을 제거하고 분위수 범위(기본값은 IQR)에 따라 데이터 크기를 조정
공식: X_scaled = (X - X.median) / IQR
장점: 편향된 변수에 대한 변환 후 변수의 분산을 더 잘 보존하기 때문에 이상치 제거에 효과적

 

💡 사이킷런에서 사용하기

from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import RobustScaler

 

Q. 셋 중 가장 민감하지 않은 스케일링 방법은? 🤔

A. Robust

 

- 표준화(Z-score) : 평균을 빼준 다음 표준편차로 나누기

- Min-Max : 0~1 사이값으로 만들기

- Robust : 중간값을 빼준 다음 IQR값으로 나누기. 이상치에 덜 민감

 

Q. 스케일링을 해주면 어떻게 변하는가? 🤔

스케일링을 했을 때 분포는 변하지 않는다.

X축의 범위를 보면, min-max의 경우 0~1의 범위를 갖고 있고 표준화와 robust는 비슷해보이지만 차이가 존재한다.

(표준화는 평균을 빼준 다음 표준편차로 나누고, robust는 중간값을 빼준 다음 IQR로 나눈다.)

 

Q. 기술통계로 봤을 때 각 스케일링의 특징 🤔
StandardScaling: 평균이 0, 분산이 1
Min-Max: 최솟값이 0 최댓값이 1
Robust Scaling: 중간값(중앙값, 50%, 2사분위수)가 0

4. 사이킷런에서 스케일링 해보기

ss = StandardScaler()

train["파생변수"] = ss.fit(train["변수"]).transform(train["변수"])

이렇게 입력하면 아래와 같은 오류메세지를 볼 수 있다.

Expected 2D array, got 1D array instead:

 

Q. 왜 오류가 날까?🤔

StandardScaler의 fit 에는 matrix를 넣어주어야 하기 때문에 시리즈가 아닌 데이터프레임 형태로 넣어주기 위해 [[ ]]를 사용해야 한다.
반환값도 matrix 형태이기 때문에 새로운 파생변수를 생성하고자 한다면 데이터프레임 형태로 파생변수를 만들어주어야 한다.

ss = StandardScaler()
train[["파생변수"]] = ss.fit(train[["변수"]]).transform(train[["변수"]])

fit_transform()을 하게 되면 fit(), transform()을 한번에 해줄 수 있다.

 

💡 trainform? 🤔

사이킷런의 다른 기능에서는 fit => predict 를 했었지만 전처리에서는 fit => transform을 사용한다.

transform은 SalePrice의 분포를 토대로 StandardScaler에 맞게 값을 변환시켜주는 역할을 한다.

스케일링을 예시로 fit 은 계산하기 위한 평균, 중앙값, 표준편차가 필요하다면 해당 데이터를 기준으로 기술통계값을 구하고 그 값을 기준으로 transform 에서 계산을 적용해서 값을 변환해 줍니다

 

💡주의사항

피처에 fit_transform은 train에만 사용하고 transform은 train, test에 사용한다.

fit은 test에 사용하지 않는데,  test에도 fit을 하게되면 train과 test의 기준이 달라지기 때문이고,

스케일링의 기준을 train에 맞춰주어야 한다.

(전처리할 때 train을 기준으로 전처리해주듯이 Scaling의 기준도 마찬가지이다.)

 

따라서 test 에는 train을 기준으로 학습한 것을 바탕으로 transform 만 해야한다.

(학습할 때도 fit은  train 에만 해주는 것과 동일한 느낌이다)

댓글