내일배움캠프(본캠프)

[내일배움캠프] 본캠프 4/30

anscodus 2026. 4. 30. 21:00

오늘 한 일

문제풀이

데이터분석 심화 팀 과제 - 머신러닝

 

결측값 채우기

더보기

결측치가 많은 데이터라서 결측치를 채울 방법을 선정해야 함.

df_mean = df.copy()
df_median = df.copy()
df_knn = df.copy()

import pandas as pd
from sklearn.impute import SimpleImputer, KNNImputer

imputer_mean = SimpleImputer(strategy='mean')
df_mean.iloc[:, :] = imputer_mean.fit_transform(df_mean)

imputer_median = SimpleImputer(strategy='median')
df_median.iloc[:, :] = imputer_median.fit_transform(df_median)

imputer_knn = KNNImputer(n_neighbors=5)
df_knn.iloc[:, :] = imputer_knn.fit_transform(df_knn)

 3가지 방식(mean, median, KNN) 으로 결측값을 채운 후, 원본 표준편차와의 차이를 비교하여 가장 차이가 적은 방법을 선정 함.(머신러닝에 적용하기 위해 가장 차이가 적은 것이 좋음)

 

# 각 방법별로 원본 표준편차와의 차이 평균 구하기
def get_std_diff(imputed_df, original_df):
    diff = abs(original_df.std() - imputed_df.std())
    return diff.mean() # 전체 컬럼의 평균적인 차이

print(f"평균 대체 시 전체 왜곡도: {get_std_diff(df_mean, df):.4f}")
print(f"중앙값 대체 시 전체 왜곡도: {get_std_diff(df_median, df):.4f}")
print(f"KNN 대체 시 전체 왜곡도: {get_std_diff(df_knn, df):.4f}")
평균 대체 시 전체 왜곡도: 0.6713
중앙값 대체 시 전체 왜곡도: 0.6711
KNN 대체 시 전체 왜곡도: 0.5130

 상관관계 heatmap도 만들었는데 한 눈에 알아보기 어려워서 barplot을 만듦

 

 

 각 컬럼이 기존 데이터와 얼마나 차이가 나는지를 비교함.

knn이 가장 차이가 적은 것을 알 수 있음

 

=> knn으로 결측값 채우고 머신러닝 시작

 

 

머신러닝

더보기

1. 데이터 분리

# 데이터 분리 (train/test)

from sklearn.model_selection import train_test_split
from sklearn.impute import KNNImputer

X = df.drop('label', axis=1)
y = df['label']


X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42,stratify=y)
#stratify=y 추가


imputer = KNNImputer(n_neighbors=5)


X_train_imputed = pd.DataFrame(imputer.fit_transform(X_train), columns=X_train.columns)


X_test_imputed = pd.DataFrame(imputer.transform(X_test), columns=X_test.columns)

 

2. 스케일링

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()


X_train_scaled = pd.DataFrame(scaler.fit_transform(X_train_imputed), columns=X_train_imputed.columns)

X_test_scaled = pd.DataFrame(scaler.transform(X_test_imputed), columns=X_test_imputed.columns)

 

3. SMOTE

from imblearn.over_sampling import SMOTE

smote = SMOTE(random_state=42)


X_train_final, y_train_final = smote.fit_resample(X_train_scaled, y_train)

# 결과 확인
print("--- SMOTE 적용 결과 ---")
print(f"증식 전 학습 데이터 구성:\n{y_train.value_counts()}")
print(f"증식 후 학습 데이터 구성:\n{y_train_final.value_counts()}")

 

4. 최종 모델 학습 (Randonforest, XG Boost, LightGBM)

from sklearn.ensemble import RandomForestClassifier

# 1. 모델 생성
model = RandomForestClassifier(n_estimators=100, random_state=42)

# 2. 학습 (최종 전처리가 끝난 데이터 투입)
model.fit(X_train_final, y_train_final)
from sklearn.metrics import f1_score

# 정답예측
y_pred = model.predict(X_test_scaled)

# F1-Score
score = f1_score(y_test, y_pred, pos_label=1)

print(f"최종 모델의 F1-Score (불량 감지 성능): {score:.4f}")
from sklearn.metrics import accuracy_score

# 스케일링 및 SMOTE 처리 후 테스트 데이터 예측
y_pred_final = model.predict(X_test_scaled)

# 정확도 계산 및 출력
accuracy_final = accuracy_score(y_test, y_pred_final)
print(f"최종 모델의 정확도 (스케일링 및 SMOTE 적용 후): {accuracy_final:.4f}")
from sklearn.metrics import recall_score

# 재현율 계산 (불량 데이터인 1번 클래스 기준)
recall = recall_score(y_test, y_pred_final, pos_label=1)

print(f"최종 모델의 재현율 (불량 감지 성능): {recall:.4f}")

 Randomforest 성능 요약

  • F1-Score : 0.5027
  • 정확도 : 0.6776
  • 재현율 : 0.8064

 

1차 -> RF만 함 

피드백) stratify필요. 스케일링 사용 한 근거 필요. xgboost랑 lightgbm 하고 ROC, AUC curve

 

XG Boost

from xgboost import XGBClassifier
from sklearn.metrics import f1_score, accuracy_score, recall_score

# XGBoost 분류기 초기화
# n_estimators: 부스팅 라운드 수, learning_rate: 학습률, random_state: 재현성을 위한 시드
xgb_model = XGBClassifier(n_estimators=100, learning_rate=0.1, random_state=42, eval_metric='logloss')

# 모델 학습
xgb_model.fit(X_train_final, y_train_final)
# 테스트 데이터로 예측
y_pred_xgb = xgb_model.predict(X_test_scaled)

# F1-Score 계산 (불량 감지 성능)
f1_xgb = f1_score(y_test, y_pred_xgb, pos_label=1)
print(f"XGBoost 모델의 F1-Score (불량 감지 성능): {f1_xgb:.4f}")

# 정확도 계산
accuracy_xgb = accuracy_score(y_test, y_pred_xgb)
print(f"XGBoost 모델의 정확도: {accuracy_xgb:.4f}")

# 재현율 계산
recall_xgb = recall_score(y_test, y_pred_xgb, pos_label=1)
print(f"XGBoost 모델의 재현율 (불량 감지 성능): {recall_xgb:.4f}")

XG Boost 성능 요약

  • F1-Score: 0.5101
  • 정확도: 0.6724
  • 재현율: 0.8443

 

 

LightGBM

from lightgbm import LGBMClassifier
from sklearn.metrics import f1_score, accuracy_score, recall_score

# LightGBM 분류기 초기화
lgbm_model = LGBMClassifier(random_state=42)

# 모델 학습
lgbm_model.fit(X_train_final, y_train_final)
# 테스트 데이터로 예측
y_pred_lgbm = lgbm_model.predict(X_test_scaled)

# F1-Score 계산 (불량 감지 성능)
f1_lgbm = f1_score(y_test, y_pred_lgbm, pos_label=1)
print(f"LightGBM 모델의 F1-Score (불량 감지 성능): {f1_lgbm:.4f}")

# 정확도 계산
accuracy_lgbm = accuracy_score(y_test, y_pred_lgbm)
print(f"LightGBM 모델의 정확도: {accuracy_lgbm:.4f}")

# 재현율 계산
recall_lgbm = recall_score(y_test, y_pred_lgbm, pos_label=1)
print(f"LightGBM 모델의 재현율 (불량 감지 성능): {recall_lgbm:.4f}")

Light GBM 성능 요약

  • F1-Score: 0.5189
  • 정확도: 0.6782
  • 재현율: 0.8588

 

 

ROC,AUC Curve

from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt

# 한글 폰트 설정 (이전 설정 다시 적용)
plt.rcParams['font.family'] = ['NanumGothic', 'Malgun Gothic', 'sans-serif']
plt.rcParams['axes.unicode_minus'] = False # 마이너스 기호 깨짐 방지

plt.figure(figsize=(10, 8))

# Random Forest Model
y_pred_proba_rf = model.predict_proba(X_test_scaled)[:, 1]
fpr_rf, tpr_rf, _ = roc_curve(y_test, y_pred_proba_rf)
roc_auc_rf = auc(fpr_rf, tpr_rf)
plt.plot(fpr_rf, tpr_rf, label=f'Random Forest (AUC = {roc_auc_rf:.4f})')

# XGBoost Model
y_pred_proba_xgb = xgb_model.predict_proba(X_test_scaled)[:, 1]
fpr_xgb, tpr_xgb, _ = roc_curve(y_test, y_pred_proba_xgb)
roc_auc_xgb = auc(fpr_xgb, tpr_xgb)
plt.plot(fpr_xgb, tpr_xgb, label=f'XGBoost (AUC = {roc_auc_xgb:.4f})')

# LightGBM Model
y_pred_proba_lgbm = lgbm_model.predict_proba(X_test_scaled)[:, 1]
fpr_lgbm, tpr_lgbm, _ = roc_curve(y_test, y_pred_proba_lgbm)
roc_auc_lgbm = auc(fpr_lgbm, tpr_lgbm)
plt.plot(fpr_lgbm, tpr_lgbm, label=f'LightGBM (AUC = {roc_auc_lgbm:.4f})')

# Plot settings
plt.plot([0, 1], [0, 1], 'k--', label='Random Chance')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic (ROC) Curve')
plt.legend(loc='lower right')
plt.grid(True)
plt.show()

print(f"Random Forest 모델의 ROC AUC: {roc_auc_rf:.4f}")
print(f"XGBoost 모델의 ROC AUC: {roc_auc_xgb:.4f}")
print(f"LightGBM 모델의 ROC AUC: {roc_auc_lgbm:.4f}")
Random Forest 모델의 ROC AUC: 0.9584
XGBoost 모델의 ROC AUC: 0.9512
LightGBM 모델의 ROC AUC: 0.9585