토론 게시판에 첫 게시물 작성

제목: RandomForestClassifier를 한 번 돌려봤습니다

AUC score는 0.7289 밖에 안 나왔지만, 시도한 방법을 공유하고 제가 놓친 것과 새로 시도할 수 있는 방법들에 대해 토론하면 좋을 것 같아서 적어봅니다.

예제 코드에 있는 Gradient Boosting 방식과 Random Forest 방식에는 각각 장단점이 있는데, 전자보다 후자가 (noisy한 데이터에의 경우) 일반화 성능에 있어서 나을 수 있다는 정보를 바탕으로 시도하게 되었습니다.

성능이 더 떨어진 것에 대해 제가 확인, 혹은 추측한 바로는 다음 몇 가지가 있습니다.

  1. output.csv를 확인해보면 예측된 확률값이 고르게 퍼져 있지 않고, 대부분 ‘0.0’이며 가끔 ‘1.0’, ‘0.4’ 등이 등장하는 등 매우 극단적으로 분포하고 있다.

  2. 애초에 Overfitting이 큰 문제가 되고 있는 상황이 아니었기 때문에, 일반화 성능에 초점을 맞출 필요가 없었다.

  3. feature extraction 등 유의미한 전처리가 뒷받침 되지 않은 상태에서 모델만 바꾸는 것으로는 성능 향상을 기대하기 힘들다.

  4. 주어진 예제 코드를 변경하는 과정에서, 기존에 적용되던 (어느 정도 성능을 보이던) 하이퍼 파라미터와 feature engineering 등의 효과를 기대할 수 없게 되었다.

  5. 하이퍼 파라미터 최적화가 적용되지 않았다.

코드는 간단하게 from sklearn.ensemble import RandomForestClassifier 로 모델을 불러온 뒤, baseline3에서 호출하는 make_lgb_oof_prediction 함수의 몇몇 부분을 rfc 모델로 대체해서 baseline3를 실행했습니다.

def make_lgb_oof_prediction(train, y, test, features, categorical_features='auto', model_params=None, folds=10):
    x_train = train[features]
    x_test = test[features]
    
    # 테스트 데이터 예측값을 저장할 변수
    test_preds = np.zeros(x_test.shape[0])
    
    # Out Of Fold Validation 예측 데이터를 저장할 변수
    y_oof = np.zeros(x_train.shape[0])
    
    # 폴드별 평균 Validation 스코어를 저장할 변수
    score = 0
    
    # 피처 중요도를 저장할 데이터 프레임 선언
    fi = pd.DataFrame()
    fi['feature'] = features
    
    # Stratified K Fold 선언
    skf = StratifiedKFold(n_splits=folds, shuffle=True, random_state=SEED)

    for fold, (tr_idx, val_idx) in enumerate(skf.split(x_train, y)):
        # train index, validation index로 train 데이터를 나눔
        x_tr, x_val = x_train.loc[tr_idx, features], x_train.loc[val_idx, features]
        y_tr, y_val = y[tr_idx], y[val_idx]
        
        print(f'fold: {fold+1}, x_tr.shape: {x_tr.shape}, x_val.shape: {x_val.shape}')
        
        # 모델 훈련 (randomforest)
        rfc = RandomForestClassifier(n_estimators = 1000, max_depth=32)
        rfc.fit(x_tr, y_tr)

        # Validation 데이터 예측
        val_preds = rfc.predict(x_val)
        
        # Validation index에 예측값 저장 
        y_oof[val_idx] = val_preds
        
        # 폴드별 Validation 스코어 측정
        print(f"Fold {fold + 1} | AUC: {roc_auc_score(y_val, val_preds)}")
        print('-'*80)

        # score 변수에 폴드별 평균 Validation 스코어 저장
        score += roc_auc_score(y_val, val_preds) / folds
        
        # 테스트 데이터 예측하고 평균해서 저장
        test_preds += rfc.predict(x_test) / folds
    
        # 폴드별 피처 중요도 저장
        fi[f'fold_{fold+1}'] = rfc.feature_importances_

        del x_tr, x_val, y_tr, y_val
        gc.collect()
        
    print(f"\nMean AUC = {score}") # 폴드별 Validation 스코어 출력
    print(f"OOF AUC = {roc_auc_score(y, y_oof)}") # Out Of Fold Validation 스코어 출력
        
    # 폴드별 피처 중요도 평균값 계산해서 저장 
    fi_cols = [col for col in fi.columns if 'fold_' in col]
    fi['importance'] = fi[fi_cols].mean(axis=1)
    
    return y_oof, test_preds, fi