주제
3차 프로젝트 4일차
- 어제에 이어 랜덤 포레스트 모델을 파인 튜닝
- 특성 중요도가 낮은 피쳐 제외
- 피쳐 엔지니어링 : 총상환원금 비율과 총상환이자 비율 추가
1. 피쳐 엔지니어링
- 새로운 피쳐인 총상환원금 비율과 총상환이자 비율을 생성하여 추가함
- 팀 회의 때 멘토님께서 피쳐 엔지니어링할 때 '비율' 같은 것을 많이 추가한다고 하셨던 걸 인상깊게 들었음
# 총상환원금비율과 총상환이자비율 추가
train['총상환원금비율'] = train['총상환원금'] / train['대출금액']
train['총상환이자비율'] = train['총상환이자'] / train['대출금액']
2. 모델 훈련
- 이번에는 총 11개의 피쳐들로 다시 훈련을 시도해보았음
- 이번에는 정확도와 F1 점수를 같이 보기 위해 성능 평가 메트릭을 추가
from sklearn.metrics import make_scorer, f1_score, accuracy_score
scoring = {
'accuracy': make_scorer(accuracy_score),
'f1_score_macro': make_scorer(f1_score, average='macro')
}
scores = cross_validate(rf, X, y, cv=StratifiedKFold())
accuracy_scores = scores['test_accuracy']
f1_scores = scores['test_f1_score_macro']
print("Accuracy Scores:", accuracy_scores)
print("F1 Scores:", f1_scores)
avg_accuracy_score = np.mean(accuracy_scores)
avg_f1_score = np.mean(f1_scores)
print("Average Accuracy Score:", avg_accuracy_score)
print("Average F1 Score:", avg_f1_score)

- 새로운 피쳐를 2개 추가한 후에 정확도가 크게 증가했다.
- F1 score도 나쁘지 않은 점수가 나옴
- 특성 중요도 확인
- 정확도가 크게 증가한 이유는 역시 새로운 피쳐 2개 덕분이었다.
- 총상환원금비율과 총상환이자비율의 중요도가 가장 높았다
- 여기서 중요도가 낮은 근로기간, 대출목적 등은 추후에 제거하여 다시 훈련하기로 결정

3. 하이퍼파라미터 튜닝
- 이전에는 기본 모델을 사용했고 이번에는 하이퍼 파라미터 튜닝을 통해 최적의 파라미터 조합을 찾아보았다
- 이보다 더 섬세한 옵션을 주고 싶었지만 튜닝 특성상 CPU 작업을 오래 하기 때문에 10분이상을 기다려도 결과가 나오지 않아 내 노트북이 버틸 수 있을 정도로만 주었다.
# hyperparameter tuning
# 더 많은 옵션을 추가하고 싶지만 노트북 성능상 불가능했음
params = {
'n_estimators' : [100, 200],
'max_depth' : [5, 10],
'min_samples_split' : [2, 5],
'min_samples_leaf' : [1, 2],
}
- 튜닝은 GridSearchCV로 진행
# 훈련
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_validate, StratifiedKFold, GridSearchCV
from sklearn.metrics import make_scorer, f1_score, accuracy_score
rf = RandomForestClassifier(random_state=42)
grid_search = GridSearchCV(estimator=rf, param_grid=params, n_jobs=-1)
grid_search.fit(X,y)
scores = cross_validate(rf, X, y, cv=StratifiedKFold(), scoring=scoring)
- 최적의 파라미터 확인
# 최적의 파라미터 확인
print(grid_search.best_params_)

- 최적의 파라미터로 튜닝한 모델과 앞선 훈련 세트에서 중요도가 낮은 피쳐 3개를 제외한 새로운 훈련 세트의 조합으로 다시 한번 학습
rf = RandomForestClassifier(
n_estimators=200,
max_depth=10,
min_samples_split=5,
min_samples_leaf=1,
n_jobs=-1,
random_state=42
)
scores = cross_validate(rf, X, y, cv=StratifiedKFold(), scoring=scoring)

- 정확도는 93.2%, F1 score는 88.1%로 오히려 감소했다.
- 기본값 모델보다 튜닝된 모델의 정확도가 더 떨어져서 혹시 훈련 세트에 문제가 있는 것은 아닐까 하고 피쳐 11개인 세트와 8개인 세트, 그리고 기본값 모델, 튜닝된 모델로 가능한 조합을 다 시도해봤다.
- 결과는 다음과 같다 :
| 모델 종류 | 기본 모델 | 튜닝된 모델 | ||
| 피쳐 개수 | 피쳐 11개 | 피쳐 8개 | 피쳐 11개 | 피쳐 8개 |
| 정확도 | 0.948 | 0.945 | 0.935 | 0.933 |
| F1 score | 0.928 | 0.924 | 0.888 | 0.881 |
- 튜닝된 모델이 더 정확도가 낮고, 피쳐의 개수가 적을수록 정확도가 떨어졌다
- 튜닝을 할때 노트북 성능의 한계로 조금 더 많고 촘촘한 옵션을 사용해보지 못한 것이 원인이 아닐까 예상해본다
- 어느정도 정확도에 도달했을 때는 0.01을 올리는 것도 쉽지 않은 일인 것 같다
4. 이상치 제거
- 우선 가장 중요도가 높은 피쳐들의 이상치 확인을 위해 박스플롯을 그렸다
- 이때 스케일링 전 데이터를 사용

- 가장 중요도가 높았던 총상환원금비율의 이상치만 제거
- IQR 방법을 사용
- 1사분위 * 1.5 보다 작거나 3사분위 * 1.5 보다 크면 이상치로 간주
# 이 중 특성 중요도가 가장 높았던 총상환원금비율의 이상치 제거 시도
# IQR 기법 사용
Q1 = train[['총상환원금비율']].quantile(0.25)
Q3 = train[['총상환원금비율']].quantile(0.75)
IQR = Q3 - Q1
threshold = 1.5
outliers = (train[['총상환원금비율']] < (Q1 - threshold * IQR)) | (train[['총상환원금비율']] > (Q3 + threshold * IQR))
train_no_outliers = train[~outliers.any(axis=1)]
print("이상치 제거 후 :")
print(train_no_outliers)
- 이상치 제거가 잘 되었는지 다시 확인하기 위해 시각화

- 이상치가 제거된 데이터 총 95546개를 가지고 진행
5. 시도 정리
- 다시 스케일링을 해주고 피쳐 여러 개를 소거해가며 기본 모델에 주입
- 여태까지의 시도를 총정리 해본 결과 :

- 가장 결과가 좋았던 조합은 총상환원금비율의 이상치를 제거한 피쳐 4개(총상환원금비율, 총상환이자비율, 총상환원금_log, 총상환이자_log)를 기본 모델에 주입한 것이었다
- 마지막에 시도해본 조합인데 정확도와 f1 점수 모두 올라서 놀랐다.
- 이상치를 제거한 데이터를 아직 튜닝 모델에 넣어보진 않았지만 가설을 세워보자면 기본 모델보다 성능이 떨어질 것 같다.
- 튜닝 모델은 한번 돌리는 데에도 시간이 걸리기 때문에 마지막에 시도해보기로 하였다.
'Data Science > TIL (Today I Learned)' 카테고리의 다른 글
| 프로그래머스 데이터분석 데브코스 1기 - 61일차 (0) | 2024.02.19 |
|---|---|
| 프로그래머스 데이터분석 데브코스 1기 - 60일차 (2) | 2024.02.16 |
| 프로그래머스 데이터분석 데브코스 1기 - 58일차 (1) | 2024.02.14 |
| 프로그래머스 데이터분석 데브코스 1기 - 57일차 (1) | 2024.02.13 |
| 프로그래머스 데이터분석 데브코스 1기 - 56일차 (1) | 2024.02.12 |