본문으로 건너뛰기

011 첫 번째 분류 모델 만들기

키워드: 분류, 첫 번째 모델

개요

이제 FLAML의 기본 개념을 배웠으니, 실제 데이터로 첫 번째 분류 모델을 만들어 보겠습니다. 유방암 진단 데이터세트를 사용해 악성/양성을 분류하는 모델을 처음부터 끝까지 구현합니다.

실습 환경

  • Python 버전: 3.11 권장
  • 필요 패키지: flaml[automl], pandas, scikit-learn, matplotlib
pip install flaml[automl] pandas scikit-learn matplotlib

프로젝트 개요

목표

유방암 세포의 특성을 기반으로 악성(malignant) 또는 양성(benign)을 분류

데이터세트

  • 이름: Wisconsin Breast Cancer Dataset
  • 샘플 수: 569개
  • 특성 수: 30개 (세포 핵의 특성)
  • 타겟: 0(악성), 1(양성)

Step 1: 라이브러리 임포트

# 011 필수 라이브러리
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 011 FLAML
from flaml import AutoML

# 011 scikit-learn
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import (
accuracy_score,
classification_report,
confusion_matrix,
roc_auc_score,
roc_curve
)

# 011 경고 무시 (선택)
import warnings
warnings.filterwarnings('ignore')

print("라이브러리 로드 완료!")

Step 2: 데이터 로드 및 탐색

# 011 데이터 로드
data = load_breast_cancer()

# 011 DataFrame으로 변환
df = pd.DataFrame(data.data, columns=data.feature_names)
df['target'] = data.target

# 011 기본 정보 확인
print("="*60)
print("데이터 기본 정보")
print("="*60)
print(f"데이터 크기: {df.shape}")
print(f"\n컬럼 목록:")
for i, col in enumerate(df.columns, 1):
print(f" {i:2d}. {col}")

실행 결과

============================================================
데이터 기본 정보
============================================================
데이터 크기: (569, 31)

컬럼 목록:
1. mean radius
2. mean texture
3. mean perimeter
...
31. target

타겟 분포 확인

print("\n타겟 분포:")
print(df['target'].value_counts())
print(f"\n클래스 비율:")
print(f" 양성(1): {(df['target']==1).mean()*100:.1f}%")
print(f" 악성(0): {(df['target']==0).mean()*100:.1f}%")

실행 결과

타겟 분포:
1 357
0 212
Name: target, dtype: int64

클래스 비율:
양성(1): 62.7%
악성(0): 37.3%

기초 통계량

print("\n기초 통계량 (일부 컬럼):")
print(df[['mean radius', 'mean texture', 'mean perimeter', 'target']].describe())

Step 3: 데이터 전처리

# 011 특성(X)과 타겟(y) 분리
X = df.drop('target', axis=1)
y = df['target']

# 011 결측치 확인
print("결측치 확인:")
print(f" 총 결측치: {X.isnull().sum().sum()}")

# 011 데이터 분할 (80% 학습, 20% 테스트)
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2,
random_state=42,
stratify=y # 클래스 비율 유지
)

print(f"\n데이터 분할 완료:")
print(f" 학습 데이터: {X_train.shape[0]}개")
print(f" 테스트 데이터: {X_test.shape[0]}개")

실행 결과

결측치 확인:
총 결측치: 0

데이터 분할 완료:
학습 데이터: 455개
테스트 데이터: 114개

Step 4: FLAML AutoML 실행

# 011 AutoML 객체 생성
automl = AutoML()

# 011 설정
settings = {
"task": "classification",
"time_budget": 60, # 60초
"metric": "accuracy",
"estimator_list": ["lgbm", "xgboost", "rf", "extra_tree"],
"seed": 42,
"verbose": 1
}

print("="*60)
print("FLAML AutoML 학습 시작")
print("="*60)
print(f"시간 예산: {settings['time_budget']}초")
print(f"최적화 지표: {settings['metric']}")
print(f"탐색 모델: {settings['estimator_list']}")
print()

# 011 학습 실행
automl.fit(X_train, y_train, **settings)

실행 결과

============================================================
FLAML AutoML 학습 시작
============================================================
시간 예산: 60초
최적화 지표: accuracy
탐색 모델: ['lgbm', 'xgboost', 'rf', 'extra_tree']

[flaml.automl.logger: INFO] Iteration 1, current learner lgbm
[flaml.automl.logger: INFO] at 0.3s, best lgbm's error=0.0330, ...
[flaml.automl.logger: INFO] Iteration 2, current learner lgbm
[flaml.automl.logger: INFO] at 0.4s, best lgbm's error=0.0308, ...
...
[flaml.automl.logger: INFO] retrain lgbm for 0.1s
[flaml.automl.logger: INFO] Best ML model: lgbm

Step 5: 학습 결과 확인

print("="*60)
print("학습 결과")
print("="*60)

# 011 최적 모델
print(f"최적 모델: {automl.best_estimator}")

# 011 최적 하이퍼파라미터
print(f"\n최적 하이퍼파라미터:")
for key, value in automl.best_config.items():
print(f" {key}: {value}")

# 011 검증 점수
print(f"\n검증 정확도: {1 - automl.best_loss:.4f}")

실행 결과

============================================================
학습 결과
============================================================
최적 모델: lgbm

최적 하이퍼파라미터:
n_estimators: 63
num_leaves: 4
min_child_samples: 7
learning_rate: 0.2677
log_max_bin: 8
colsample_bytree: 0.9867
reg_alpha: 0.0009
reg_lambda: 0.0087

검증 정확도: 0.9714

Step 6: 테스트 세트 평가

# 011 예측
y_pred = automl.predict(X_test)
y_prob = automl.predict_proba(X_test)[:, 1]

print("="*60)
print("테스트 세트 평가")
print("="*60)

# 011 정확도
accuracy = accuracy_score(y_test, y_pred)
print(f"정확도: {accuracy:.4f}")

# 011 ROC AUC
roc_auc = roc_auc_score(y_test, y_prob)
print(f"ROC AUC: {roc_auc:.4f}")

# 011 분류 리포트
print(f"\n분류 리포트:")
print(classification_report(y_test, y_pred,
target_names=['악성', '양성']))

실행 결과

============================================================
테스트 세트 평가
============================================================
정확도: 0.9737
ROC AUC: 0.9967

분류 리포트:
precision recall f1-score support

악성 0.98 0.95 0.96 43
양성 0.97 0.99 0.98 71

accuracy 0.97 114
macro avg 0.97 0.97 0.97 114
weighted avg 0.97 0.97 0.97 114

Step 7: 결과 시각화

혼동 행렬

# 011 혼동 행렬
cm = confusion_matrix(y_test, y_pred)

plt.figure(figsize=(8, 6))
plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
plt.title('Confusion Matrix')
plt.colorbar()

classes = ['악성', '양성']
tick_marks = np.arange(len(classes))
plt.xticks(tick_marks, classes)
plt.yticks(tick_marks, classes)

# 011 숫자 표시
for i in range(cm.shape[0]):
for j in range(cm.shape[1]):
plt.text(j, i, format(cm[i, j], 'd'),
ha="center", va="center", fontsize=20,
color="white" if cm[i, j] > cm.max()/2 else "black")

plt.xlabel('예측')
plt.ylabel('실제')
plt.tight_layout()
plt.savefig('confusion_matrix.png', dpi=100)
plt.show()

ROC 곡선

# 011 ROC 곡선
fpr, tpr, _ = roc_curve(y_test, y_prob)

plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, color='blue', lw=2, label=f'ROC curve (AUC = {roc_auc:.4f})')
plt.plot([0, 1], [0, 1], color='gray', lw=1, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.legend(loc="lower right")
plt.tight_layout()
plt.savefig('roc_curve.png', dpi=100)
plt.show()

Step 8: 모델 저장

import pickle

# 011 모델 저장
model_path = 'breast_cancer_classifier.pkl'
with open(model_path, 'wb') as f:
pickle.dump(automl, f)

print(f"모델 저장 완료: {model_path}")

# 011 저장된 모델 테스트
with open(model_path, 'rb') as f:
loaded_model = pickle.load(f)

test_accuracy = accuracy_score(y_test, loaded_model.predict(X_test))
print(f"불러온 모델 정확도: {test_accuracy:.4f}")

전체 코드 (복사용)

"""
FLAML 첫 번째 분류 모델 - 유방암 진단
"""
import pandas as pd
import numpy as np
from flaml import AutoML
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report, roc_auc_score
import pickle

# 1. 데이터 로드
data = load_breast_cancer()
X, y = data.data, data.target

# 2. 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)

# 3. FLAML 학습
automl = AutoML()
automl.fit(
X_train, y_train,
task="classification",
time_budget=60,
metric="accuracy",
seed=42
)

# 4. 평가
y_pred = automl.predict(X_test)
print(f"최적 모델: {automl.best_estimator}")
print(f"정확도: {accuracy_score(y_test, y_pred):.4f}")
print(classification_report(y_test, y_pred, target_names=['악성', '양성']))

# 5. 저장
with open('model.pkl', 'wb') as f:
pickle.dump(automl, f)

정리

  • 유방암 데이터세트로 분류 모델을 만들었습니다.
  • FLAML이 60초 내에 lgbm을 최적 모델로 선택했습니다.
  • 테스트 정확도 97.37%, ROC AUC 0.9967을 달성했습니다.
  • 모델을 pickle로 저장하여 재사용할 수 있습니다.

다음 글 예고

다음 글에서는 첫 번째 회귀 모델 만들기에 대해 알아보겠습니다. 당뇨병 데이터세트를 사용해 회귀 문제를 해결합니다.


FLAML AutoML 마스터 시리즈 #011