반응형

오늘은 Day14에 대한 내용이다.

Today's Assignment - day 14

이번 튜토리얼에서는 gradient boosting으로 모델을 구축하고 최적화하는 방법에 대해서 배운다.
이 방법은 많은 Kaggle competition에서 우위를 차지하며 다양한 데이터셋에서 최첨단 최첨단 결과를 달성한다.

XGBoost

Introduction

지금까지 kaggle코스의 대부분동안, 많은 의사결정나무의 예측을 평균화 하는 것만으로 단일 의사결정 나무보다 더 나은 성능을 달성하는  RandomForest 방법으로 예측을 했다. 

우리는 RandomForest방법을 "ensemble method" (앙상블 기법)이라고 한다. 
정의에 따르면, 앙상블 기법은 여러 모델(예: 랜덤포레스트의 경우 여러 트리)의 예측을 결합한다.

다음으로 GradientBoosting 이라는 또다른 앙상블 기법에 대해 알아보겠다.

Gradient Boosting

Gradient boosting은 모델을 앙상블에 반복해서 추가하는 방법이다.

예측이 매우 단순할 수 있는 단일 모델로 앙상블을 초기화 하는 것으로 시작한다.(예측이 매우 부정확하더라도 앙상블에 대한 후속 추가는 이러한 오류를 해결할 것이다.)

그런다음 사이클을 시작한다.

  • 우선, 현재 앙상블을 사용하여 데이터 세트의 각 관측치에 대한 예측을 생성한다. 예측을 위해 앙상블에 있는 모든 모델의 예측을 추가한다. 
  • 이러한 예측은 loss function(손실함수)[ex:평균 제곱 오차(mse)] 를 계산하는 데 사용된다.
  • 그런다음 loss function을 사용하여 앙승블에 추가될 새 모델에 fit(적합)한다. 특히, 이 새 모델을 앙상블에 추가하면 손실이 줄어들도록 모델 매개변수를 결정한다. (참고: "gradient"의 gradient는 loss function에 대한 gradient descent(경사 하강법)을 사용하여 이 새 모델의 매개변수를 결정한다는 사실을 나타낸다.)
  • 마지막으로 앙상블에 새 모델을 추가하고..
  • 반복한다!

Example

먼저 X_train, X_valid, y_train 및 y_valid에 train data 와 validation data를 로드한다.

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')

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

# Select target
y = data.Price

# Separate data into training and validation sets
X_train, X_valid, y_train, y_valid = train_test_split(X, y)

이 예에서는 XGBoost 라이브러리로 작업한다. XGBoost는 성능과 속도에 중점을 둔 몇 가지 추가 기능으로 Gradient boosting을 구현하는 Extreme Gradient Boosting의 약자이다. (Scikit-learn에는 다른 버전의 Gradient Boosting이 있지만 XGBoost에는 몇 가지 기술적 이점이 있다.)

다음 코드 셀에서는 XGBoost(xgboost.XGBRegressor)용 scikit-learn API를 가져온다. 이것은 우리가 scikit-learn에서 하는 것처럼 모델을 제작하고 fit(적합)시킬 수 있게 해준다. 출력에서 볼 수 있듯이 XGBregressor 클래스에는 조정 가능한 매개변수가 많다. 곧 이러한 매개 변수에 대해 알아 볼 것이다.

from xgboost import XGBRegressor

my_model = XGBRegressor()
my_model.fit(X_train, y_train)

그다음 우리는 예측하고, 모델을 평가 한다.

from sklearn.metrics import mean_absolute_error

predictions = my_model.predict(X_valid)
print("Mean Absolute Error: " + str(mean_absolute_error(predictions, y_valid)))

 

Parameter Tuning

XGBoost는 정확도와 train속도에 큰영향을 미칠 수 있는 몇 가지 매개변수를 가지고 있다. 
첫번쨰 매개변수는 다음과 같다.

n_estimators
n_estimators는 위에서 설명한 모델링 사이클을 몇 번이나 거쳐야 하는지를 지정한다. 앙상블에 포함된 모델의 수와 같다.

  • 값이 너무 낮으면 underfitting이 발생하여 훈련데이터와 테스트 데이터 모두에서 부정확한 예측이 발생한다.
  • 값이 너무 높으면 overfitting이 발생하여 훈련데이터에 대한 정확한 예측이 발생하지만 테스트 데이터에 대한 부정확한 예측이 발생한다.

일반적인 값의 범위는 100-1000이지만 아래에 설명된 learning_rate 매개변수에 따라 크게 달라진다.
앙상블 모델 수를 설정하는 코드는 다음과 같다.

my_model = XGBRegressor(n_estimators=500)
my_model.fit(X_train, y_train)

 


early_stopping_rounds
early_stopping_rounds는 n_estimators에 대한 이상적인 값을 자동으로 찾는 방법을 제공한다. early stopping을 사용하면 n_estimators에 대한 hard stop에 있지 않더라도 validation score의 개선이 중지되면 모델 반복이 중지된다. 
즉, n_estimators에 높은 값을 설정한 다음, early_stopping_rounds를 사용하여 반복을 중지할 최적의 시간을 찾는 것이 현명하다.

랜덤확률로 인해 validation score가 향상되지 않는 single round(단일 라운드)가 발생하지 않기 때문에 중지하기 전에 허용할 직선 저하 라운드의 수(rounds of straight deterioration)를 지정해야 한다. 
early_stopping_rounds = 5를 설정하는 것이 합리적인 선택이다. 
이 경우 validation score가 5회 연속 악화되는 경우 중지한다.

early_stopping_rounds를 사용할 떄 validation score를 계산하기 위해 일부 데이터를 따로 설정해야 한다.
이는 eval_set 매개변수를 설정하여 수행된다.

early stopping을 포함하도록 위의 예를 수정할 수 있다.

my_model = XGBRegressor(n_estimators=500)
my_model.fit(X_train, y_train, 
             early_stopping_rounds=5, 
             eval_set=[(X_valid, y_valid)],
             verbose=False)

나중에 모든 데이터로 모델을 fit(적합) 시키려면 n_estimators를 early stopping과 함께 실행할 때 도출된 최적의 값으로 설정한다.

 

learning_rate

각 구성 요소 모델의 예측을 단순히 합산하여 예측을 얻는 대신 각 모델의 예측을 추가하기 전에 작은 숫자(학습률)을 곱한후 이를 추가할 수 있다.

이것은 우리가 앙상블에 추가하는 각각의 트리가 우리에게 덜 도움이 된다는 것을 의미한다. 따라서 과적합 없이 n_estimators에 더 높은 값을 설정할 수 있다. early stopping을 사용하면 적절한 트리수가 자동으로 결정된다. 

일반적으로 학습률이 낮고 추정치가 많으면 정확한 XGBoost모델을 만들 수 있지만, 사이클을 통해 더 많은 반복을 수행하기 때문에 모델을 학습하는데 더 오래 걸린다. 기본적으로 XGBoost는 learning_rate = 0.1로 설정한다.



learning_rate를 변경하기 위해 예를 수정하면 다음과 같다.

my_model = XGBRegressor(n_estimators=1000, learning_rate=0.05)
my_model.fit(X_train, y_train, 
             early_stopping_rounds=5, 
             eval_set=[(X_valid, y_valid)], 
             verbose=False)

 

n_jobs

런타임이 고려되는 대규모 데이터 세트에서는 병렬처리를 사용하여 모델을 더 빠르게 구축할 수 있다.
n_jobs 매개변수를 머신의 코어수와 동일하게 설정하는 것이 일반적이다. 소규모 데이터셋에서는 이 방법이 도움이 되지 않는다.

결과모델은 더 이상 나아지지 않을 것이기 떄문에, 시간에 대한 미세 최적화는 일반적으로 방해가 될 뿐이다. 그러나 fit명령동안 대기하는데 오랜 시간을 소비해야하는 대규모 데이터세트에서유용하다.

수정된 예는 다음과 같다.

my_model = XGBRegressor(n_estimators=1000, learning_rate=0.05, n_jobs=4)
my_model.fit(X_train, y_train, 
             early_stopping_rounds=5, 
             eval_set=[(X_valid, y_valid)], 
             verbose=False)

Conclusion

XGBoost는 표준 테이블 형식 데이터(이미지 및 비디오와 같은 좀더 특이한 유형의 데이터와 대조적으로 Pandas DataFrames에 저장하는 데이터 유형)로 작업하기 위한 최고의 소프트웨어 라이브러리이다. 신중한 매개변수 조정을 통해 매우 정확한 모델을 학습할 수 있다.

XGBoost를 실습한 코드를 공유한다!
https://github.com/mgkim-developer/30-Days-of-ML-with-Kaggle/blob/main/30-days-of-ml-day-14-xgboost.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

 

 

Data Leakage

이 튜토리얼에서는 Data Leakage(데이터 누출)이 무엇인지, 어떻게 방지하는지 알아본다.
예방법을 모르면 누수가 자주 발생하여 미묘하고 위험한 방식으로 모델을 망칠 수 있다.
따라서 이것은 데이터 사이언티스트들을 위한 가장 중요한 개념 중 하나이다.

Introduction

Data leakage(or leakage)은 훈련 데이터에 target에 대한 정보가 포함되어 있을 때 발생하지만 모델을 예측에 사용할 경우 유사한 데이터를 사용할 수 없다. 이로인해 train dataset(및 validation)의 성능이 향상되지만, 모델은 production에서 저조한 성능을 보일 것이다.

즉, Data Leakage로 인해 모델에 대한 결정을 내리기 시작할 떄까지 모델이 정확해 보이게 하고, 그 후에는 모형이 매우 부정확해진다.

Data Leakage에는 크게 두가지 유형이 있다

  • target leakage (타겟 누출)
  •  train-test contamination ( train-test 오염)

 

Target leakage

Target leakage는 예측자가 예측할 때 사용할 수 없는 데이터를 포함할 때 발생한다. 
 특정 feature가 좋은 예측을 만드는데 도움이 되는지 여부가 아니라, 데이터를 사용할 수 있게 되는 타이밍 또는 시간 순서의 관점에서 Target leakage에 대해 생각하는 것이 중요하다.

아래 예제가 도움이 될 것이다. 누가 폐렴에 걸릴지 예측하고 싶다고 상상해보자.
원시 데이터의 맨 위 몇 행은 다음과 같다.

사람들은 pneumonia(폐렴)에 걸린 후 회복하기 위해 항생제를 복용한다. 원시 데이터는 해당 열간의 강한 관계를 보여주지만 take_antibiotic_medicine은 got_pneumonia값이 결정된 후 자주 변경된다. 이것은 target leakage이다. 

이 모델은 항생제 투약에 대해 False값을 가진 사람은 폐렴이 없다는 것을 알 수 있다. 
validation data는 train data와 동일한 출처에서 제공되기 떄문에 패턴이 validation에서 반복되고 모델은 큰 검증(교차검증)점수를 갖게 된다.

그러나 이후에 실제 환경에 배포하면 모델이 매우 부정확 할 것이다. 
왜냐하면 폐렴에 걸릴 환자라도 미래의 건강에 대해 예측해야 할 때 아직 항생제를 투여받지 않았기 때문이다.

이러한 유형의 data leakage를 방지하려면 target value가 실현된 후 업데이트(또는 생성)된 모든 변수를 제외해야한다.

Train-Test Contamination

다른 유형의 data leakage는 train data와 validation data를 구별하지 못할 때 발생한다.
validation 검사는 모델이 이전에 고려하지 않은 데이터에 대해 예측을 수행하는 방식을 측정하기 위한 것임을 기억하자.
validation data가 전처리 동작에 영향을 미치는 경우 이 프로세스를 미묘한 방식으로 손상시킬 수 있다. 이를 때때로 train-test contamination(트레인-테스트 오염)라고 한다.

예를 들어, train_test_split()을 호출하기 전에 전처리(ex:fitting imputer for missing values)를 실행한다고 상상해보자. 
최종 결과는? 해당 모델은 좋은 validation score를 얻어 예측자에게 모델에 대한 신뢰도를 높일 수 있지만, 모델을 배포할 때는 성능이 좋지 않을 수 있다.

결국 validation data 또는 test data를 예측 방법에 통합했기 때문에 새 데이터로 일반화하지 못하더라도 해당 특정 데이터에 대해서는 잘 예측하는 것이다. 이문제는 복잡한 피쳐 엔지니어링을 수행할 때 훨씬 더 미묘해지고 위험해진다.

검증이 단순한 traint-test 분할을 기반으로 하는 경우 전처리 단계의 피팅을 포함하여 모든 유형의 피팅에서 validation data를 제외하자. scikit-learn 파이프라인을 사용하면 더 쉽다. 
cross-validation을 사용할 때 파이프라인 내에서 전처리를 수행하는 것이 더욱 중요하다!

Example

이번 예에서는 target leakage를 감지하고 제거하는 한 가지 방법을 배운다.

신용카드 어플리케이션에 대한 데이터 세트를 사용한다. 

import pandas as pd

# Read the data
data = pd.read_csv('../input/aer-credit-card-data/AER_credit_card_data.csv', 
                   true_values = ['yes'], false_values = ['no'])

# Select target
y = data.card

# Select predictors
X = data.drop(['card'], axis=1)

print("Number of rows in the dataset:", X.shape[0])
X.head()

신용카드 어플리케이션에 대한 정보는 DataFrame X에 저장했다. 이를 사용하여 Series y에서 어떤 응용프로그램이 승인되었는지 예측할 것이다.

이것은 small data set이므로 모델 품질의 정확한 측정을 보장하기 위해 cross-validation을 사용할 것이다.

from sklearn.pipeline import make_pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

# Since there is no preprocessing, we don't need a pipeline (used anyway as best practice!)
my_pipeline = make_pipeline(RandomForestClassifier(n_estimators=100))
cv_scores = cross_val_score(my_pipeline, X, y, 
                            cv=5,
                            scoring='accuracy')

print("Cross-validation accuracy: %f" % cv_scores.mean())

경험상 정확도가 98%에 달하는 모델을 찾아보기 매우어렵다. 그런일이 있긴 하지만, 데이터에서 누출이 있는지 좀 더 자세히 조사해야 할 정도로 흔치 않다. 

다음은 데이터 탭에서 찾을 수 있는 데이터 요약이다.

  • card: 신용카드 신청이 승인된 경우 1, 승인되지 않은 경우0
  • reports: 주요 비방 신고 건수
  • age: n세 + 12세
  • income: 연간 소득(10000으로 나눈 값)
  • share: 연간 소득 대비 월별 신용카드 지출 비율
  • expenditure: 월 평균 신용카드 지출액
  • owner: 집을 소유한 경우1, 임대인 경우0
  • selfemp1: 자영업자인 경우1, 그렇지 않을 경우0
  • dependents: +1 부양가족수
  • months: 현재 주소에 거주하는 개월
  • majorcards: 보유하고 있는 주요 신용카드 수
  • active: 활성 신용 계정 수

몇 가지 변수가 의심스러워 보인다. 예를 들면 지출은 이 카드에 대한 지출을 의미하는가? 아니면 신청 전에 사용한 카드에 대한 지출을 의미하는가?

이 시점에서 기본 데이터 비교가 매우 유용할 수 있다.

expenditures_cardholders = X.expenditure[y]
expenditures_noncardholders = X.expenditure[~y]

print('Fraction of those who did not receive a card and had no expenditures: %.2f' \
      %((expenditures_noncardholders == 0).mean()))
print('Fraction of those who received a card and had no expenditures: %.2f' \
      %(( expenditures_cardholders == 0).mean()))

위와 같이 카드를 받지 않은 사람은 모두 지출이 없었고 카드를 받은 사람은 2%만 지출이 없었다. 우리의 모델이 높은 정확도를 보인다는 것은 놀라운 일이 아니다. 그러나 이것은 아마도 그들이 신청한 카드에 대한 지출을 의미하는 target leakage 사례로 보인다.

share(연간 소득 대비 월별 신용카드 지출 비율)는 expenditure(월 평균 신용카드 지출액)에 의해 결정되기 때문에, 배제되어야 한다.
active(활성 신용 계정 수) 변수와 majorcards(보유하고 있는 주요 신용카드 수)변수는 명확하지는 않지만, 설명으로 볼 때 관련 변수처럼 들린다.  대부분의 경우 데이터를 생성한 사람을 추적하여 자세한 정보를 확인할 수 없다면 보수적으로 판단하여 안전한 것이 좋다.

# Drop leaky predictors from dataset
potential_leaks = ['expenditure', 'share', 'active', 'majorcards']
X2 = X.drop(potential_leaks, axis=1)

# Evaluate the model with leaky predictors removed
cv_scores = cross_val_score(my_pipeline, X2, y, 
                            cv=5,
                            scoring='accuracy')

print("Cross-val accuracy: %f" % cv_scores.mean())

정확도가 상당히 낮아서 실망할 수 있다. 그러나 새 응용프로그램에서 사용할 때 약 80%의 정확도가 나올 것으로 예상할 수 있는 반면, leakage모델은 그보다 훨씬 더 나쁠 것이다.

Conclusion

데이터 사이언스 응용프로그램에서  Data leakage는 수백만 달러의 실수 일 수 있다. train data 및 valid data 의 신중한 분리는 train-test contamination(학습-테스트 오염) 방지할 수 있으며, 파이프라인은 이러한 분리를 구현하는 데 도움이 될 수 있다. 마찬가지로 주의, 상식 및 데이터 탐색의 조합은 target leakage를 식별하는 데 도움이 될 수 있다.
즉, target에 대한 완벽한 정보를 제공하는 feature는 생략해야한다.

Data leakage를 실습한 코드를 공유한다.(해당 예제의 예시가  이해하기 쉬운 예제로 구성되어있다. 꼭 참고하길 바람)
https://github.com/mgkim-developer/30-Days-of-ML-with-Kaggle/blob/main/30-days-of-ml-day-14-data-leakage.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

 

반응형