본문 바로가기

파이썬/전처리

데이터 스케일링 반드시 필요한 전처리 과정! fit_transform과 transform의 차이

모델을 학습시키기에 앞서 데이터 전처리는 꼭 필요하다. 특성별로 값의 범위가 다 다르기 때문에 어떤 특성은 값이 너무 작고 어떤 특성은 값이 너무 크다면 알고리즘 학습 시 0으로 수렴하거나 무한으로 발산해버리면서 원하는 결과값이 나오지 않을 수 있다.

 

 

특히 SVM이나 신경망 알고리즘 같은 경우 데이터의 스케일에 매우 민감하기 때문에 알고리즘에 맞는 데이터 특성값 조정은 반드시 선행되어야 한다.

 

 

데이터 스케일링의 종류

1. StandardScaler

평균=0, 표준편차=1로 조정해서 모든 특성이 같은 크기를 갖게 한다.

 

2. MinMaxScaler

최대값=1, 최소값=0으로 조정, 아웃라이어에 취약

 

3. RobustScaler

중앙값=0, IQR(1분위~3분위값)=1로 조정, 아웃라이어 영향을 최소화하며 정규분포보다 더 넓게 분포

 

4. MaxAbsScaler

0을 기준으로 절대값이 가장 큰 수가 1 또는 -1이 되도록 조정, 양수 데이터로만 구성된 데이터셋에서는 아웃라이어에 민감

 

데이터 스케일링을 하는 이유가 아웃라이어의 영향을 최소화하는 것이기 때문에 보통은 이상치 영향을 가장 적게 받는 StandardScaler 혹은 RobustScaler를 주로 사용한다. 모두 사이킷런에서 모듈을 제공한다.

 

 

fit_transform( )과 transform( )의 차이

 

스케일링을 할 때 꼭 사용하는게 fit_transform(), fit(), transform()메서드이다. 

fit_transform()은 말그대로 fit()과 transform()을 한번에 처리할 수 있게 하는 메서드인데 조심해야 하는 것은 테스트 데이터에는 fit_transform()메서드를 쓰면 안된다.

 

 

fit()은 데이터를 학습시키는 메서드이고 transform()은 실제로 학습시킨 것을 적용하는 메서드이다.

 

 

 

fit, transform을 각각 쓰는 경우의 코드는 아래와 같다.

from sklearn.preprocessing import StandardScaler

#scaler정의
scaler = StandardScaler()

#train data에 scaler를 fit
scaler.fit(X_train)

#train data 변환
X_train_scaled = scaler.transform(X_train)

#test data 변환
X_test_scaled = scaler.transform(X_test)

 

 

1. scaler 생성

2. 학습 데이터에 대해 fit

3. 학습 데이터에 대해 transform

4. 학습데이터를 스케일링한 scaler로 테스트 데이터도 transform (fit은 하지 않음!)

 

 

학습 데이터에 fit 한 설정을 그대로 test set에도 적용하는 것이다.

이때 주의할 점은 test set에는 fit이나 fit_transform 메서드를 절대 쓰면 안된다는거!

 

 

만약 test set에도 fit을 해버리면 sclaer가 기존에 학습 데이터에 fit한 기준을 다 무시하고 테스트 데이터에 새로운 mean, variance값을 얻으면서 테스트 데이터까지 학습해버린다. 테스트 데이터는 검증을 위해 남겨둔 셋이기 때문에 반드시 주의해야 한다.

 

 

만약 fit_transform()메서드를 쓴다면 코드는 아래와 같다. fit_transform을 사용하는 것과 fit을 하고 transform을 하는거는 아주 약간의 미세한 성능 차이는 있지만 더 효율적이다.

X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = sclaer.transform(X_test)

 

추가로 train_test_split을 하기 전에 미리 전처리를 해주고 train, test분리를 해줘도 무방하다.

 

 

코드 실습

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, random_state=42)

log_reg = LogisticRegression(random_state=42)
log_reg.fit(X_train_scaled, y_train)
y_pred = log_reg.predict(X_test_scaled)

print('전처리o 성능: {:.3f}'.format(accuracy_score(y_test, y_pred)))
>>>전처리o 성능: 0.979

log_reg.fit(X_train, y_train)
y_pred2 = log_reg.predict(X_test)

print('전처리x 성능: {:.3f}'.format(accuracy_score(y_test, y_pred2)))
>>>전처리x 성능: 0.965

 

전처리를 하면 전처리를 하지 않았을 때보다 성능이 개선된다는 것까지 확인 가능하다.

 

from sklearn.preprocessing import RobustScaler, MinMaxScaler, MaxAbsScaler

#RobustScaler
scaler2 = RobustScaler()
X_train_scaled2 = scaler.fit_transform(X_train)
X_test_scaled2 = scaler.transform(X_test)

log_reg.fit(X_train_scaled2, y_train)
y_pred2 = log_reg.predict(X_test_scaled2)

#MinMaxScaler
scaler3 = MinMaxScaler()
X_train_scaled3 = scaler.fit_transform(X_train)
X_test_scaled3 = scaler.transform(X_test)

log_reg.fit(X_train_scaled3, y_train)
y_pred3 = log_reg.predict(X_test_scaled3)

#MaxAbsScaler
scaler4 = MaxAbsScaler()
X_train_scaled4 = scaler.fit_transform(X_train)
X_test_scaled4 = scaler.transform(X_test)

log_reg.fit(X_train_scaled4, y_train)
y_pred4 = log_reg.predict(X_test_scaled4)


print('StandardScaler 성능: {:.3f}'.format(accuracy_score(y_test, y_pred)))
print('RobustScaler 성능: {:.3f}'.format(accuracy_score(y_test, y_pred2)))
print('MinMaxScaler 성능: {:.3f}'.format(accuracy_score(y_test, y_pred3)))
print('MaxAbsScaler 성능: {:.3f}'.format(accuracy_score(y_test, y_pred4)))

>>>StandardScaler 성능: 0.979
>>>RobustScaler 성능: 0.979
>>>MinMaxScaler 성능: 0.979
>>>MaxAbsScaler 성능: 0.979

 

혹시나 해서 스케일러별로 다 fit해서 성능을 비교해봤는데 차이가 없다 ㅋㅋㅋ 아마 cancer데이터셋의 값들이 다 비슷비슷해서 그런게 아닐까 싶다.