Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

DF_Project — 분류 / 회귀 프로젝트

데이터 동아리 DF(Data First) 봄 단기 프로젝트(머신러닝 기초 7주 과정)의 최종 산출물입니다. 매주 배운 내용을 따로 연습하는 데서 그치지 않고, 7주치를 하나의 문제에 합쳐서 적용해보는 것이 목표였습니다.

노트북 문제 데이터
DF_Classification_Project.ipynb 이진 분류 심장병 진단
DF_Regression_Project.ipynb 회귀 주택 가격 예측

과정에서 배운 것과 이 프로젝트에서 쓴 것

주차 배운 내용 이 프로젝트에서
1–2주 NumPy · pandas 전처리 · EDA
3주 교차검증 · GridSearchCV · 인코딩 · 스케일링 StratifiedKFold · GridSearchCV · LabelEncoder / OneHotEncoder
4주 오차행렬 · 정밀도/재현율 · threshold · ROC-AUC 지표 5종 동시 평가 · Binarizer로 임계값 조정
5주 결정트리 · 랜덤포레스트 · GBM · XGBoost · LightGBM · 앙상블(Voting) 4개 모델 비교 → 튜닝된 3개로 Soft Voting
6주 선형회귀 · 경사하강법 · 규제 회귀 노트북
7주 PCA · K-Means · GMM 차원축소 후 군집 변수 실험

각 주차의 내용을 개별 실습으로 끝내지 않고, 한 데이터셋 위에서 순서대로 쌓아 올려 단계마다 성능이 어떻게 변하는지 비교했습니다.


1. 분류 — 심장병 진단

도메인부터 확인하고, 그 해석을 실제 피처로 만들었습니다

cp(chest pain type)는 0~3 숫자로 들어 있지만 의학적으로는 성격이 다른 범주입니다.

의미
0 전형적 협심증 — 가슴을 짓누르거나 쥐어짜는 통증
1 비전형적 협심증 — 찌르는 듯한 통증
2 비협심증성 통증 — 근육통·소화불량·스트레스 등
3 무증상

그런데 cp를 그대로 쓰면 모델이 0 < 1 < 2 < 3 이라는 순서로 읽습니다. 실제로는 0이 가장 위험하고 3이 가장 덜 위험해서 순서가 반대에 가깝습니다.

그래서 위험도 기준으로 파생 변수를 만들어 원본 컬럼을 대체했습니다.

def cp_risk_group(cp):
    if cp == 0:      return 'high_risk'   # 전형적 협심증
    elif cp in [1,2]: return 'mid_risk'
    else:             return 'low_risk'   # 무증상

df['cp_risk_group'] = df['cp'].apply(cp_risk_group)
df_final = df_final.drop(columns=['cp'])

도메인 해석을 글로만 적어두지 않고 피처 엔지니어링으로 연결한 부분입니다.

진행 순서

EDA → 파생변수·인코딩 → 결정트리 / 랜덤포레스트
   → 부스팅 (XGBoost, LightGBM) → GridSearchCV 튜닝
   → 튜닝된 3개로 Voting 앙상블
   → PCA → K-Means / GMM 군집 변수 추가 → 전후 비교

분할 단계부터 stratify=y를 줘서 레이블 비율을 학습/테스트에 동일하게 유지했습니다.

결과

단계 성능
결정 트리 정확도 0.9167
랜덤 포레스트 정확도 0.9363
KFold 교차검증 (5) 평균 0.9047
StratifiedKFold 교차검증 (5) 평균 0.9126
GridSearchCV 최적화 CV 최고 0.9484
최종 테스트 세트 정확도 0.9706 · 정밀도 0.9626 · 재현율 0.9810 · F1 0.9717 · AUC 0.9703

최적 하이퍼파라미터 — RandomForest max_depth=7, min_samples_split=2, n_estimators=100 / XGBoost colsample_bytree=0.7, learning_rate=0.1

같은 데이터에 KFold(0.9047)와 StratifiedKFold(0.9126)를 나란히 돌려 층화 추출의 차이를 수치로 확인했습니다.

안 된 실험도 남겨둡니다 — 군집 변수는 오히려 성능을 떨어뜨렸습니다

7주차에 배운 PCA·K-Means·GMM으로 군집 라벨을 새 피처로 넣으면 성능이 오를까를 실험했습니다.

조건 Voting 앙상블 정확도
원본 데이터 0.9383
K-Means 군집 변수 추가 0.9292
GMM 군집 변수 추가 0.9292

둘 다 떨어졌습니다. 비지도 학습으로 만든 파생 변수가 항상 이득은 아니라는 걸 직접 확인했고, 결과를 지우는 대신 그대로 남겼습니다.

cp_risk_group(도메인 기반)은 살아남고 군집 라벨(통계 기반)은 밀린 셈이라, 파생 변수는 만드는 방식보다 근거가 있는지가 중요하다는 쪽으로 이해하고 있습니다.


2. 회귀 — 주택 가격 예측

StandardScaler → 파생변수(building_age_group) 인코딩 → LinearRegressionKFold(5)GridSearchCV

지표
평균 RMSE 14,091.14
평균 R² 0.7981
CV 최고 R² 0.7990

분류 노트북에 비해 설명이 얕습니다. 회귀는 기본 파이프라인을 한 번 통과시켜보는 데 목적을 뒀고, 정리는 분류 쪽에 집중했습니다. 스케일링을 분할 전에 전체 데이터에 적용한 점은 데이터 누수 관점에서 다시 짚어볼 부분으로 남겨둡니다.


사용 기술

Python pandas NumPy scikit-learn XGBoost LightGBM matplotlib seaborn

  • 전처리 StandardScaler · LabelEncoder · OneHotEncoder
  • 검증 train_test_split(stratify) · KFold · StratifiedKFold · cross_val_score
  • 튜닝 GridSearchCV
  • 평가 accuracy · precision · recall · f1_score · roc_auc_score · confusion_matrix · Binarizer
  • 앙상블 VotingClassifier
  • 차원축소·군집 PCA · KMeans · GaussianMixture

About

DF 동아리 ML 7주 과정 최종 프로젝트 — 심장병 분류 · 주택가격 회귀

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages