사이킷런은 데이터를 변환하는 대부분의 로직에서 fit()과 transform()을 쌍으로 사용합니다. 예를 들어 sklearn.preprocessing의 StandardScaler, MinMaxScaler 나 PCA클래스, 그리고 텍스트의 Feature Vectorization 클래스들(CountVectorizer, TFIDF등) 모드 fit()과 transform()을 같이 이용합니다.

 

변환만을 생각한다면 fit() , transform()을 함께 사용하지 않고 transform()만 사용하면 될텐데 두개 메소드를 함께 사용하는 이유가 아래와 같이 있을 거라 추정됩니다(이 중 두번째 이유가 중요합니다. )

 

  1. 사이킷런의 지도학습의 주요 메소드인 fit()과 predict()와 비슷한 API로 사용자들의 보다 쉬운 이해를 돕기 위해서.
  2. 학습데이터 세트에서 변환을 위한 기반 설정(예를 들어 학습 데이터 세트의 최대값/최소값등)을 먼저 fit()을 통해서 설정한 뒤에 이를 기반으로 학습 데이터의 transform()을 수행하되 학습 데이터에서 설정된 변환을 위한 기반 설정을 그대로 테스트 데이터에도 적용하기 위해서입니다.

 

즉, 학습 데이터 세트로 fit() 된 Scaler를 이용하여 테스트 데이터를 변환할 경우에는 테스트 데이터에서 다시 fit()하지 않고 반드시 그대로 이 Scaler를 이용하여 transform()을 수행해야 합니다.

 

가령 아래와 같이 Iris 학습 데이터 세트로 MinMaxScaler() 를 생성한 뒤 fit()하고 transform() 한 뒤 Classifier로 학습 했다면

예측 시, 먼저 테스트 데이터 세트를  반드시 학습 데이터로 Scaling된 MinMaxScaler를 이용하여 fit()한 뒤 transform() 해야 됩니다.

 

즉, 학습할 때와 동일한 기반 설정으로 동일하게 테스트 데이터를 변환해야 하는 것입니다.

 

학습 데이터에서 Scale된 데이터를 기반으로 Classifier가 학습이 되었기 때문에 이렇게 학습된 Classifier가 예측을 할 때에도 학습 데이터의 Scale 기준으로 테스트 데이터를 변환 한 뒤 predict해야 합니다.

 

from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.metrics import accuracy_score

# 붓꽃 데이터 세트를 로딩합니다. 
iris = load_iris()
iris_data = iris.data
iris_label = iris.target
X_train, X_test, y_train, y_test = train_test_split(iris_data, iris_label, 
                                                    test_size=0.2, random_state=2)
# MinMaxScaler() Scaler객체 생성. 
scaler = MinMaxScaler()
# 학습 데이터에 대해서 fit(), transform() 수행. 
scaler.fit(X_train)
scaled_X_train = scaler.transform(X_train)

# 테스트 데이터에서는 다시 fit(), transform()이나 fit_transform()을 수행하지 않고 transform만 수행. 
scaled_X_test = scaler.transform(X_test)

lr = LogisticRegression()
lr.fit(scaled_X_train, y_train)
pred = lr.predict(scaled_X_test)
print('예측 정확도: {0:.4f}'.format(accuracy_score(y_test,pred)))

 

fit_transform()을 fit() 과 transform() 함께 수행하는 메소드 입니다.

 

기존의 fit() 과 transform() 각각을 수행하는 번거로움을 줄여줍니다.  위 코드를 예로 들면

 

scaler.fit(X_train)
scaled_X_train = scaler.transform(X_train)은

=> scaled_X_train = scaler.fit_transform(X_train) 과 같이 한 라인으로 대체 될 수 있습니다. 

 

하지만 테스트 데이터에 scaled_X_test = scaler.fit_transform(X_test)를 적용해서는 안됩니다.

 

이를 수행하면 scaler 객체가 기존에 학습 데이터에 fit 했던 기준을 모두 무시하고 다시 테스트 데이터를 기반으로 기준을 적용하기 때문입니다. 

 

때문에 테스트 데이터에 fit_transform()을 적용해서는 안됩니다.

 

이런 번거로움을 피하기 위해 학습과 테스트 데이터로 나누기 전에 먼저 Scaling등의 데이터 전처리를 해주는 것이 좋습니다. 아래 코드에서는 학습과 테스트 데이터로 나누기 전에 Scaling을 적용합니다. fit(), transform()을 순차적으로 써도 좋고 fit_transform()으로 변환해도 무방합니다.

 

from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.metrics import accuracy_score

# 붓꽃 데이터 세트를 로딩합니다. 
iris = load_iris()
iris_data = iris.data
iris_label = iris.target

# MinMaxScaler() Scaler객체 생성. 
scaler = MinMaxScaler()
# 학습 데이터, 테스트 데이터로 나누기 전에 fit과 transform 으로 변환. fit_transform() 도 무방.  
scaler.fit(iris.data)
scaled_iris_data = scaler.transform(iris.data)
# scale된 iris_data로 학습과 테스트 데이터를 나눔.
X_train, X_test, y_train, y_test = train_test_split(scaled_iris_data, iris_label, 
                                                    test_size=0.2, random_state=2)

lr = LogisticRegression()
lr.fit(scaled_X_train, y_train)
pred = lr.predict(scaled_X_test)
print('예측 정확도: {0:.4f}'.format(accuracy_score(y_test,pred)))

 

fit(), transform(), fit_transform()을 어떤 데이터 세트에 적용하냐에 따라 사용이 달라 질 수 있으며 이는 위의 Scaler 뿐만 아니라 PCA, Feature Vectorizer 클래스등 모든 Transformer 클래스에 동일하게 적용되는 규칙입니다.

 

 

'💡 AI > ML' 카테고리의 다른 글

ML - Confusion Matrix, Precision, Recall  (0) 2021.11.18
ML - 평가(evaluation)  (0) 2021.11.12
ML - Estimator의 fit()과 비지도 학습의 fit()의 차이  (0) 2021.09.15
ML - 타이타닉 생존자 예측  (0) 2021.09.15
ML - 정규화  (0) 2021.09.15
복사했습니다!