<jupyter_start><jupyter_text>7장. XGBoost로 외계 행성 찾기 *아래 링크를 통해 이 노트북을 주피터 노트북 뷰어(nbviewer.org)로 보거나 구글 코랩(colab.research.google.com)에서 실행할 수 있습니다.*      주피터 노트북 뷰어로 보기        구글 코랩(Colab)에서 실행하기<jupyter_code># 노트북이 코랩에서 실행 중인지 체크합니다.
import sys
if 'google.colab' in sys.modules:
    !pip install -q --upgrade xgboost
    !wget -q https://raw.githubusercontent.com/rickiepark/handson-gb/main/Chapter07/exoplanets.csv.zip

!unzip -o exoplanets.csv.zip
# 경고 끄기
import warnings
warnings.filterwarnings('ignore')

import xgboost as xgb
xgb.set_config(verbosity=0)<jupyter_output><empty_output><jupyter_text>외계 행성 찾기 외계 행성 데이터셋<jupyter_code>import pandas as pd
df = pd.read_csv('exoplanets.csv', nrows=400)
df.head()
df['LABEL'].value_counts()<jupyter_output><empty_output><jupyter_text>그래프 시각화<jupyter_code>import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
sns.set()

X = df.iloc[:,1:]
y = df.iloc[:,0] - 1

def light_plot(index):
    y_vals = X.iloc[index]
    x_vals = np.arange(len(y_vals))
    plt.figure(figsize=(15,8))
    plt.xlabel('Number of Observations')
    plt.ylabel('Light Flux')
    plt.title('Light Plot ' + str(index), size=15)
    plt.plot(x_vals, y_vals)
    plt.show()
light_plot(0)
light_plot(37)
light_plot(1)<jupyter_output><empty_output><jupyter_text>데이터 준비<jupyter_code>df.info()
# 누락된 값의 개수를 셉니다.
df.isnull().sum().sum()<jupyter_output><empty_output><jupyter_text>초기 XGBClassifier<jupyter_code># XGBRegressor를 임포트합니다.
from xgboost import XGBClassifier

# accuracy_score를 임포트합니다.
from sklearn.metrics import accuracy_score

# train_test_split를 임포트합니다.
from sklearn.model_selection import train_test_split

# 데이터를 훈련 세트와 테스트 세트로 나눕니다.
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=2)
# XGBClassifier를 초기화합니다.
model = XGBClassifier(booster='gbtree')

# 훈련 세트로 모델을 훈련합니다.
model.fit(X_train, y_train)

# 테스트 세트에 대한 예측을 만듭니다.
y_pred = model.predict(X_test)

score = accuracy_score(y_pred, y_test)

print('점수: ' + str(score))<jupyter_output>점수: 0.89<jupyter_text>오차 행렬 분석하기 confusion_matrix<jupyter_code>from sklearn.metrics import confusion_matrix
confusion_matrix(y_test, y_pred)<jupyter_output><empty_output><jupyter_text>classification_report<jupyter_code>from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))<jupyter_output>precision    recall  f1-score   support

           0       0.91      0.98      0.94        88
           1       0.60      0.25      0.35        12

    accuracy                           0.89       100
   macro avg       0.75      0.61      0.65       100
weighted avg       0.87      0.89      0.87       100<jupyter_text>다른 측정 방법  recall_score<jupyter_code>from sklearn.metrics import recall_score
recall_score(y_test, y_pred)<jupyter_output><empty_output><jupyter_text>불균형 데이터 리샘플링 언더샘플링 xgb_clf 함수<jupyter_code>def xgb_clf(model, nrows):

    df = pd.read_csv('exoplanets.csv', nrows=nrows)
    # 데이터를 X와 y로 나눕니다.
    X = df.iloc[:,1:]
    y = df.iloc[:,0] - 1

    # 데이터를 훈련 세트와 테스트 세트로 나눕니다.
    X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=2)

    # 훈련 세트에서 모델을 훈련합니다.
    model.fit(X_train, y_train)

    # 테스트 세트에 대한 예측을 만듭니다.
    y_pred = model.predict(X_test)

    score = recall_score(y_test, y_pred)
    
    print(confusion_matrix(y_test, y_pred))
    
    print(classification_report(y_test, y_pred))
        
    return score<jupyter_output><empty_output><jupyter_text>언더샘플링 테스트<jupyter_code>xgb_clf(XGBClassifier(), nrows=800)
xgb_clf(XGBClassifier(), nrows=200)
xgb_clf(XGBClassifier(), nrows=74)<jupyter_output>[[6 2]
 [5 6]]
              precision    recall  f1-score   support

           0       0.55      0.75      0.63         8
           1       0.75      0.55      0.63        11

    accuracy                           0.63        19
   macro avg       0.65      0.65      0.63        19
weighted avg       0.66      0.63      0.63        19<jupyter_text>오버샘플링<jupyter_code>df_train = pd.merge(y_train, X_train, left_index=True, right_index=True)
newdf = pd.DataFrame(np.repeat(df_train[df_train['LABEL']==1].values,
                               9,axis=0))
newdf.columns = df_train.columns
df_train_resample = pd.concat([df_train, newdf])

df_train_resample['LABEL'].value_counts()
X_train_resample = df_train_resample.iloc[:,1:]
y_train_resample = df_train_resample.iloc[:,0]
# XGBClassifier를 초기화합니다.
model = XGBClassifier()

# 훈련 세트로 모델을 훈련합니다.
model.fit(X_train_resample, y_train_resample)

# 테스트 세트에 대해 예측을 만듭니다.
y_pred = model.predict(X_test)

score = recall_score(y_test, y_pred)

print(confusion_matrix(y_test, y_pred))

print(classification_report(y_test, y_pred))

print(score)<jupyter_output>[[86  2]
 [ 8  4]]
              precision    recall  f1-score   support

           0       0.91      0.98      0.95        88
           1       0.67      0.33      0.44        12

    accuracy                           0.90       100
   macro avg       0.79      0.66      0.69       100
weighted avg       0.89      0.90      0.88       100

0.3333333333333333<jupyter_text>XGBClassifier 튜닝 가중치 조정하기 replace 메서드<jupyter_code>df['LABEL'] = df['LABEL'].replace(1, 0)
df['LABEL'] = df['LABEL'].replace(2, 1)

df['LABEL'].value_counts()<jupyter_output><empty_output><jupyter_text>scale_pos_weight<jupyter_code># 데이터를 X와 y로 나눕니다.
X = df.iloc[:,1:]
y = df.iloc[:,0]

# 데이터를 훈련 세트와 테스트 세트로 나눕니다.
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=2)
model = XGBClassifier(scale_pos_weight=10)

model.fit(X_train, y_train)

# 테스트 세트에 대한 예측을 만듭니다.
y_pred = model.predict(X_test)

score = recall_score(y_test, y_pred)

print(confusion_matrix(y_test, y_pred))

print(classification_report(y_test, y_pred))

print(score)<jupyter_output>[[86  2]
 [ 8  4]]
              precision    recall  f1-score   support

           0       0.91      0.98      0.95        88
           1       0.67      0.33      0.44        12

    accuracy                           0.90       100
   macro avg       0.79      0.66      0.69       100
weighted avg       0.89      0.90      0.88       100

0.3333333333333333<jupyter_text>XGBClassifier 튜닝 기준 모델<jupyter_code>from sklearn.model_selection import GridSearchCV, RandomizedSearchCV,StratifiedKFold, cross_val_score
kfold = StratifiedKFold(n_splits=2, shuffle=True, random_state=2)

model = XGBClassifier(scale_pos_weight=10)

# 교차 검증 점수를 계산합니다.
scores = cross_val_score(model, X, y, cv=kfold, scoring='recall')

# 재현율을 출력합니다.
print('재현율: ', scores)

# 재현율의 평균을 출력합니다.
print('재현율 평균: ', scores.mean())<jupyter_output>재현율:  [0.10526316 0.27777778]
재현율 평균:  0.1915204678362573<jupyter_text>grid_search<jupyter_code>def grid_search(params, random=False, X=X, y=y, 
                model=XGBClassifier(scale_pos_weight=10, random_state=2)): 
    
    xgb = model
    
    if random:
        grid = RandomizedSearchCV(xgb, params, cv=kfold, n_jobs=-1, 
                                  random_state=2, scoring='recall')
    else:
        # 그리드 서치 객체를 초기화합니다.
        grid = GridSearchCV(xgb, params, cv=kfold, n_jobs=-1, scoring='recall')
    
    # X_train와 y_train으로 훈련합니다.
    grid.fit(X, y)

    # 최상의 매개변수를 추출합니다.
    best_params = grid.best_params_

    # 최상의 매개변수를 출력합니다.
    print("최상의 매개변수:", best_params)
    
    # 최상의 점수를 추출합니다.
    best_score = grid.best_score_

    # 최상의 점수를 출력합니다.
    print("최상의 점수: {:.5f}".format(best_score))
grid_search(params={'n_estimators':[50, 200, 400, 800]})
grid_search(params={'learning_rate':[0.01, 0.05, 0.2, 0.3]})
grid_search(params={'max_depth':[1, 2, 4, 8]})
grid_search(params={'subsample':[0.3, 0.5, 0.7, 0.9]})
grid_search(params={'gamma':[0.05, 0.1, 0.5, 1]})
grid_search(params={'learning_rate':[0.001, 0.01, 0.03], 
                    'max_depth':[1, 2], 'gamma':[0.025, 0.05, 0.5]})
grid_search(params={'max_delta_step':[1, 3, 5, 7]})
grid_search(params={'subsample':[0.3, 0.5, 0.7, 0.9, 1], 
                    'colsample_bylevel':[0.3, 0.5, 0.7, 0.9, 1], 
                    'colsample_bynode':[0.3, 0.5, 0.7, 0.9, 1], 
                    'colsample_bytree':[0.3, 0.5, 0.7, 0.9, 1]}, random=True)<jupyter_output>최상의 매개변수: {'subsample': 0.3, 'colsample_bytree': 0.7, 'colsample_bynode': 0.7, 'colsample_bylevel': 1}
최상의 점수: 0.37865<jupyter_text>균형잡힌 서브셋<jupyter_code>X_short = X.iloc[:74, :]
y_short = y.iloc[:74]
grid_search(params={'max_depth':[1, 2, 3], 
                    'colsample_bynode':[0.5, 0.75, 1]}, 
            X=X_short, y=y_short, 
            model=XGBClassifier(random_state=2))<jupyter_output>최상의 매개변수: {'colsample_bynode': 0.5, 'max_depth': 1}
최상의 점수: 0.65205<jupyter_text>전체 데이터로 튜닝하기<jupyter_code>df_all = pd.read_csv('exoplanets.csv')
df_all['LABEL'] = df_all['LABEL'].replace(1, 0)
df_all['LABEL'] = df_all['LABEL'].replace(2, 1)

X_all = df_all.iloc[:,1:]
y_all = df_all.iloc[:,0]
df_all['LABEL'].value_counts()
weight = int(5050/37)
model = XGBClassifier(scale_pos_weight=weight)

# 교차 검증 점수를 계산합니다.
scores = cross_val_score(model, X_all, y_all, cv=kfold, scoring='recall')

# 재현율을 출력합니다.
print('재현율:', scores)

# 재현율의 평균을 출력합니다.
print('재현율 평균:', scores.mean())
grid_search(params={'learning_rate':[0.001, 0.01]}, X=X_all, y=y_all, 
            model=XGBClassifier(scale_pos_weight=weight))
grid_search(params={'max_depth':[1, 2],'learning_rate':[0.001]}, X=X_all, y=y_all, 
            model=XGBClassifier(scale_pos_weight=weight))<jupyter_output>최상의 매개변수: {'learning_rate': 0.001, 'max_depth': 2}
최상의 점수: 0.53509<jupyter_text>결과 통합<jupyter_code>def final_model(X, y, model):
    model.fit(X, y)
    y_pred = model.predict(X_all)
    score = recall_score(y_all, y_pred)
    print(score)
    print(confusion_matrix(y_all, y_pred))
    print(classification_report(y_all, y_pred))<jupyter_output><empty_output><jupyter_text>74개 샘플<jupyter_code>final_model(X_short, y_short, 
            XGBClassifier(max_depth=2, colsample_by_node=0.5, 
                          random_state=2))<jupyter_output>1.0
[[3588 1462]
 [   0   37]]
              precision    recall  f1-score   support

           0       1.00      0.71      0.83      5050
           1       0.02      1.00      0.05        37

    accuracy                           0.71      5087
   macro avg       0.51      0.86      0.44      5087
weighted avg       0.99      0.71      0.83      5087<jupyter_text>400개 샘플<jupyter_code>final_model(X, y, 
            XGBClassifier(max_depth=2, colsample_bynode=0.5, 
                          scale_pos_weight=10, random_state=2))<jupyter_output>1.0
[[4897  153]
 [   0   37]]
              precision    recall  f1-score   support

           0       1.00      0.97      0.98      5050
           1       0.19      1.00      0.33        37

    accuracy                           0.97      5087
   macro avg       0.60      0.98      0.66      5087
weighted avg       0.99      0.97      0.98      5087<jupyter_text>5,050개 샘플<jupyter_code>final_model(X_all, y_all, 
            XGBClassifier(max_depth=2, colsample_bynode=0.5, 
                          scale_pos_weight=weight, random_state=2))<jupyter_output>1.0
[[5050    0]
 [   0   37]]
              precision    recall  f1-score   support

           0       1.00      1.00      1.00      5050
           1       1.00      1.00      1.00        37

    accuracy                           1.00      5087
   macro avg       1.00      1.00      1.00      5087
weighted avg       1.00      1.00      1.00      5087
{'fraction_non_alphanumeric': 0.12305801808127798, 'fraction_numerical': 0.06767313262529623, 'mean_word_length': 2.6826115061409177, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 73, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 29, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '21', 'dir': 'jupyter-structured-clean-dedup', 'id': '511586', 'license': 'MIT', 'n_tokens_mistral': 5478, 'n_tokens_neox': 5527, 'n_words': 840, 'path': 'Chapter07/Discovering_Exoplanets.ipynb', 'repo_name': 'rickiepark/handson-gb', 'size': '11393'}