반응형

Day13이다. 오늘 알아 볼 내용은 아래와 같다.

Today's Assignment - day 13

Pipelines

Introduction

파이프라인은 데이터 사전 처리 및 모델링 코드를 체계적으로 유지하는 간단한 방법이다.
특히 파이프라인은 전처리 및 모델링 단계를 번들로 제공하므로 전체 번들을 단일 단계인 것처럼 사용할 수 있다.

많은 데이터 사이언티스트 들이 파이프라인 없이 모댈을 해킹하지만 파이프라인에는 몇가지 중요한 이점이 있다.

  1. Cleaner Code(깔끔한 코드): 전처리의 각 단계에서 데이터를 설명하는 것은 지저분해질 수 있다. 파이프라인을 사용하면 각 단계에서 훈련 및 검증 데이터를 수동으로 추적할 필요가 없다.
  2. Fewer Bugs(버그감소): 단계를 잘못 적용하거나 전처리 단계를 잊어버릴 가능성이 적다.
  3. Easier to Productionize(생산 용이성): 프로토타입에서 대규모 배포 가능한 것으로 모델을 전환하는 것은 놀라울 정도로 어려울 수 있다. 여기서 많은 관련 문제를 다루지는 않겠지만 파이프라인이 도움이 될 수 있다.
  4. More Options for MOdel Validation(모델 유효성 검사를 위한 추가 옵션): cross-validation

Example

이전 튜토리얼에서 사용한 Melbourne Housing 데이터셋으로 작업할 것이다.

import pandas as pd
from sklearn.model_selection import train_test_split

# Read the data
data = pd.read_csv('../input/melbourne-housing-snapshot/melb_data.csv')

# Separate target from predictors
y = data.Price
X = data.drop(['Price'], axis=1)

# Divide data into training and validation subsets
X_train_full, X_valid_full, y_train, y_valid = train_test_split(X, y, train_size=0.8, test_size=0.2,
                                                                random_state=0)

# "Cardinality" means the number of unique values in a column
# Select categorical columns with relatively low cardinality (convenient but arbitrary)
categorical_cols = [cname for cname in X_train_full.columns if X_train_full[cname].nunique() < 10 and 
                        X_train_full[cname].dtype == "object"]

# Select numerical columns
numerical_cols = [cname for cname in X_train_full.columns if X_train_full[cname].dtype in ['int64', 'float64']]

# Keep selected columns only
my_cols = categorical_cols + numerical_cols
X_train = X_train_full[my_cols].copy()
X_valid = X_valid_full[my_cols].copy()

head() 메서드를 사용하여 train data를 살펴보자.
데이터에는 범주형 데이터와 결측값이 있는 열이 모두 포함되어 있다.
파이프라인을 사용하면 두 가지 모두를 쉽게 처리할 수 있다!

X_train.head()

우리는 3단계로 전체 파이프라인을 구성한다.

Step 1: Define Preprocessing Steps

파이프라인에서 사전 처리 및 모델링 단계를 함께 번들로 묶는 방법과 마찬가지로, ColumnTransformer 클래스를 사용하여 여러 사전 처리 단계를 번들로 묶는다.

아래의 코드:

  • 숫자 데이터의 결측값을 대치한다(imputation)
  • 결측값을 대치하고(imputation) 범주형 데이터에 one-hot 인코딩을 적용한다.
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder

# Preprocessing for numerical data
numerical_transformer = SimpleImputer(strategy='constant')

# Preprocessing for categorical data
categorical_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('onehot', OneHotEncoder(handle_unknown='ignore'))
])

# Bundle preprocessing for numerical and categorical data
preprocessor = ColumnTransformer(
    transformers=[
        ('num', numerical_transformer, numerical_cols),
        ('cat', categorical_transformer, categorical_cols)
    ])

Step 2: Define the Model

RandomForest Regressor 클래스를 사용하여 random forest 모델을 정의한다.

from sklearn.ensemble import RandomForestRegressor

model = RandomForestRegressor(n_estimators=100, random_state=0)

Step 3: Create and Evaluate the Pipeline

마지막으로 Pipeline 클래스를 사용하여 전처리 및 모델링 단계를 묶는 파이프라인을 정의한다.
주의해야할 몇가지 중요한 사항이 있다.

  • 파이프라인을 사용하여 train data를 사전 처리하고 모델을 코드 한줄에 맞춘다.  (반대로 파이프 라인이 없으면 imputation, one-hot 인코딩 및 모델 학습을 별도의 단계로 수행해야 한다. 수치 및 범주형 변수를 모두 처리해야하는 경우 특히 복잡해진다.)
  • 파이프라인을 사용하면 X_valid의 처리되지 않은 피쳐를 predict() 명령에 제공하고 파이프라인은 자동으로 피쳐를 사전 처리한 후 예측을 생성한다. 그러나 파이프라인이 없으면 예측하기 전에 검증 데이터를 미리 처리해야 한다.
from sklearn.metrics import mean_absolute_error

# Bundle preprocessing and modeling code in a pipeline
my_pipeline = Pipeline(steps=[('preprocessor', preprocessor),
                              ('model', model)
                             ])

# Preprocessing of training data, fit model 
my_pipeline.fit(X_train, y_train)

# Preprocessing of validation data, get predictions
preds = my_pipeline.predict(X_valid)

# Evaluate the model
score = mean_absolute_error(y_valid, preds)
print('MAE:', score)

Conclusion

파이프라인은 기계 학습 코드를 정리하고 오류를 방지하는 데 유용하며, 정교한 데이터 사전 처리가 가능한 워크플로우에 특히 유용하다.

파이프라인을 직접 구현해본 코드를 공유한다!
https://github.com/mgkim-developer/30-Days-of-ML-with-Kaggle/blob/main/30-days-of-ml-day-13-pipelines.ipynb

 

GitHub - mgkim-developer/30-Days-of-ML-with-Kaggle: 30 Days of ML with Kaggle

30 Days of ML with Kaggle. Contribute to mgkim-developer/30-Days-of-ML-with-Kaggle development by creating an account on GitHub.

github.com

 

이번에는 Cross-Validation 에 대해서 알아보도록 하겠다.

 

Cross-Validation

Introduction

machine-learning은 반복적인 프로세스다.

사용할 예측 변수, 사용할 모형 유형, 해당 보델에 제공할 인수 등에 대한 선택 사항이 있을 것이다.
지금까지는 validation(검증)세트를 사용하여 모델 품질을 측정하여 data-driven(데이터 기반) 방식으로 이러한 선택사항을 선택했다. 

그러나 이 접근방식에는 몇 가지 단점이 있다. 이를 확인하기위해 5000개의 행이 있는 데이터 세트가 있다고 가정해보자. 일반적으로 데이터의 약 20%를 validation dataset 또는 1000개 행으로 으로 유지한다.
하지만 이렇게 하면 모델 점수를 결정할 때 임의의 여지를 남긴다. 즉, 다른 1000개 행에서는 부정확하더라도 또다른 1000개 행으로 구성된 한 세트에서는 잘 작동할 수 있다.

극단적으로 validation dataset에 데이터가 1개행만 잇다고 가정해보자.
대체 모델을 비교할 경우, 단일 데이터 포인트에 데에 어떤 모델이 가장 좋은 예측을 하는지는 대부분 운의 문제일 것이다.

일반적으로 validation dataset이 클수록 모델 품질 측정에서 randomness(랜덤성)이 적어지고 신뢰도가 높아진다.(일명 "노이즈"가 줄어든다). 안타깝게도 train data에서 row를 제거해야만 large validation dataset을 얻을 수 있으며, train dataset이 작을수록 model의 성능은 더 나빠진다!! 그래서 그에따른 해결방법중 하나인 cross-validation에 대해 알아보겠다.

What is cross-validation?

cross-validation에서는 여러 데이터하위 집합에 대한 모델링 프로세스를 실행하여 모델 품질에 대한 여러 측정값을 얻는다.

예를들어, 데이터를 전체 데이터 세트의 각 20%인 5개 조각으로 나누는 것으로 시작할 수 있다. 이 경우 데이터를 5개의 "fold"로 나누었다고 말한다.

그런다음 각 fold에 대해 하나의 실험을 실행한다.

  • Experiment 1에서는 first fold를 validation set(or holdout)으로 사용하고 나머지는 모두 train dataset으로 사용한다. 20%의 holdout set를 기반으로 모델 품질을 측정한다.
  • Experinet 2에서는 second fold의 데이터를 유지한다. (그리고 모델학습을 위해 second fold를 제외한 모든것을 train dataset으로 사용함) 그런다음 holdout set을 사용하여 모델 성능의 두번째 추정치를 얻는다.
  • 이 과정을 반복하여 모든 fold를 validation(holdout) set 으로 사용한다. 이를 종합하면 데이터의 100%가 어느 시점에 holdout으로 사용되며 데이터 세트의 모든 행을 기반으로 하는 모델 성능 측정이 끝난다. (모든 행을 동시에 사용하지 않더라도!)

When should you use cross-validation?

cross-validation은 모델 성능에 대한 보다 정확한 측정을 제공한다. 이는 많은 모델링 결정을 내리는 경우 특히 중요하다. 그러나 여러 모델(각 fold마다 하나씩)을 추정하기 때문에 실행하는 데 시간이 더 오래 걸릴 수 있다.

그렇다면 이러한 절충점을 고려할 때 각 접근 방식을 언제 사용해야 할까?

추가 계산 부담이 크지 않은 소규모 데이터 세트의 경우 교차검증(cross validation)을 실행해야 한다.
더 큰 데이터 세트의 경우 single validation set(단일 검증세트)로 충분하다 코드가 더 빠르게 실행되고 데이터가 충분하여 일부 데이터를 보류용으로 재사용할 필요가 거의 없을 것이다.
large dataset과 small dataset에 대한 단순한 임계값은 없다. 
그러나 모델을 실행하는 데 몇 분 또는 그 이하의 시간이 걸린다면 교차 검증으로 전환하는 것이 좋다.

또는 교차검증을 실행하여 각 실험의 점수가 비슷한지 확인하여 판단할 수 있다. 각 실험에서 동일한 결과가 나오면 단일 검증 세트로 충분할 것이다.

Example

입력데이터를 x로, 출력데이터를 y로 로드한다.

import pandas as pd

# Read the data
data = pd.read_csv('../input/melbourne-housing-snapshot/melb_data.csv')

# Select subset of predictors
cols_to_use = ['Rooms', 'Distance', 'Landsize', 'BuildingArea', 'YearBuilt']
X = data[cols_to_use]

# Select target
y = data.Price

그다음, imputer를 사용하여 결측값을 채우는 파이프라인과, 예측을 위한 랜덤포레스트 모델을 정의한다.

파이프라인 없이 교차 검증을 수행하는 것은 가능하긴 하지만 상당히 어렵다.
파이프라인을 사용하면 코드가 매우 간단해진다.

from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer

my_pipeline = Pipeline(steps=[('preprocessor', SimpleImputer()),
                              ('model', RandomForestRegressor(n_estimators=50,
                                                              random_state=0))
                             ])

scikit-learn에서 cross_val_score()함수를 사용하여 cross validation score을 구한다. cv매개 변수로 fold 횟수를 설정한다.

from sklearn.model_selection import cross_val_score

# Multiply by -1 since sklearn calculates *negative* MAE
scores = -1 * cross_val_score(my_pipeline, X, y,
                              cv=5,
                              scoring='neg_mean_absolute_error')

print("MAE scores:\n", scores)

스코어링 매개변수는 return 할 모델 성능 측정값을 선택한다. 
위 코드의 경우 MAE(평균 절대 오차)를 선택했다. scikit-learn용 문서에는 옵션 목록이 표시된다.

scoring='neg_mean_absolute_error' 부분에서 음의 MAE를 명시한다는 것은 조금 놀랍다.
Scikit-learn은 모든 메트릭을 정의하는 규칙을 가지고 있으므로 높은 숫자가 더 좋다.
MAE가 음수이든 양수이든 상관이 없는 이유는, 어차피 MAE자체가 예측값-실제값들의 평균이기 때문에 0에서 얼만큼 떨어져있는지가 중요하다.

print("Average MAE score (across experiments):")
print(scores.mean())

Conclusion

교차 검증을 사용하면 코드를 정리하는 추가 이점과 함꼐 모델 성능을 훨씬 더 잘 측정할 수 있다.
더이상 별도의 train set과 validation set을 추적할 필요가 없다. 특히 작은 데이터 세트의 경우 성능이 크게 향상되었다!

직접 cross-validation을 진행해본 코드를 공유한다!
https://github.com/mgkim-developer/30-Days-of-ML-with-Kaggle/blob/main/30-days-of-ml-day-13-cross-validation.ipynb

 

GitHub - mgkim-developer/30-Days-of-ML-with-Kaggle: 30 Days of ML with Kaggle

30 Days of ML with Kaggle. Contribute to mgkim-developer/30-Days-of-ML-with-Kaggle development by creating an account on GitHub.

github.com

 

 

 

반응형