• 카테고리

    질문 & 답변
  • 세부 분야

    딥러닝 · 머신러닝

  • 해결 여부

    미해결

fit & transform 과 fit_transform의 차이가 무엇인가요?

20.01.03 18:02 작성 조회수 20.7k

0

안녕하세요, 정말 좋은 강의 잘 듣고 있습니다!!

sklearn 의 클래스를 사용하다보면

fit, transform이 많이 언급되는데요.

어쩔때는 fit 하고나서 transform을 수행하거나

fit_transform으로 한번에 수행하는 경우가 있는데

두 가지의 명확한 차이가 무엇일까요?

아래의 PCA 코드로 테스트해보니까 반환되는 결과값이 소수점에서 아주 미세하게 차이가 나긴하더라구요.

from sklearn.preprocessing import StandardScaler

iris_scaled = StandardScaler().fit_transform(irisDF.iloc[:, :-1])

from sklearn.decomposition import PCA

pca = PCA(n_components=2)

#fit( )과 transform( ) 을 호출하여 PCA 변환 데이터 반환

pca.fit(iris_scaled)

iris_pca = pca.transform(iris_scaled)

print(iris_pca.shape)

# fit_transform

imp = pca.fit_transform(iris_scaled)

imp[0,0] - iris_pca[0,0]

>> -3.552713678800501e-15

답변 3

·

답변을 작성해보세요.

9

안녕하십니까,

fit, transform과 fit_transform의 차이를 좀 더 자세히 설명드렸어야 하는데, 그렇지 못한 아쉬움이 있습니다.

사이킷런은 데이터를 변환하는 대부분의 로직에서 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 클래스에 동일하게 적용되는 규칙입니다.

2

엠엠님의 프로필

엠엠

2020.12.12

https://subinium.github.io/MLwithPython-3-3/

그림과 함께 설명이 되어 있습니다!

0

천승현님의 프로필

천승현

질문자

2020.01.06

자세하게 설명해주셔서 이해가 잘 되었습니다. 감사합니다!